java拾遗

一.Enumeration与iterator

大部分旧的集合,例如Vector,hashTable具有elements()方法,此方法将获取一个Enumration实例。新的集合List等已经被重构具有iterator方法。

Enumration和Iterator功能上,都能够迭代遍历集合的方式。

Enumration:hasMoreElements(),nextElement()

Iterator:hasNext(),next(),remove()

Iterator具有遍历时remove当前元素的功能,不过此行为在不同的API中行为是不确定的,比如CopyOnWrite将会抛出UnsupportedOperationException。

二.Comparator 与Comparable

2个排序接口,Comparator是整体排序,具有方法compare(T,T),内部机制为遍历集合,采取“冒泡排序”方式。

Comarable接口,为标记对象具有“可比较”能力,其只有一个方法int compareTo(T)..

对于Collections.sort(T extends Comparable)和sort(T,Compartor c),其内部均采取了自然排序方式(冒泡排序)对集合进行排序。

 

三.RandomAccess:随机访问

此接口主要为标记,ArrayList以及CopyOnWriteList实现了此接口,但是LinkedList并没有实现此接口。此接口则表明其支持快速的随机访问。随机访问直观上说,就是能够通过index对list进行操作,而且是快速的。。LinkedList不支持“随机访问”,因为其get(index)将会产生二次项的行为(LinkedList中,根据index获取元素,内部实现为从链表的head出进行遍历,逐个访问,直到计数器累加到index为止)。

 

for (int i=0, n=list.size(); i < n; i++)

 list.get(i);

运行速度要快于以下循环:

for (Iterator i=list.iterator(); i.hasNext(); )

 i.next();

 

iterator.next()操作,内部也是通过list.get(next)方式获取元素,但是它同时还需要维护“游标”信息和检测。

 

四.HashTable,properties,HashMap:

properties继承自hashTable,hashTable和hashMap都实现了Map接口。properties更强调了“属性文件”特性,允许从IO流中读取K-V,或者将K-V写入到流(文件)。(逐行读取,=分割),HashTable是线程安全的原因:put/remove方法被同步。

 

五.StringTokenizer与Scanner

StringTokennizer是一个轻量级的基于String字符串“标记符”切割的辅助类,并基于此特性提供了相应的遍历操作,其实此类已经不建议使用,它最终产生的结果和String.split几乎一样,而且性能却稍差,它本身并没有使用快速“正则表达式”而是基于字符串的查找。

Scanner,“扫描器”,具有根据自定“分隔符”逐个匹配字符串的能力,其可以“扫描”字符串,也可以操作文件,底层基于正则表达式,

是一种高效的文本内容匹配API。其提供了很多便捷的方法,比如nextInt、nextLong等使调用者无需在对数据进行判断。

String source = "12.1nameactionnull1";

Scanner scanner = new Scanner(source).useDelimiter("\\t");

System.out.println(source);

while(scanner.hasNext()){

System.out.println(scanner.next());

}

 

六.Timer

定时器工具,启动一个后台线程,定期执行一次任务,或者按照频率执行任务。与每个 Timer 对象相对应的是单个后台线程(任务被单线程执行,区别于SchedulerExecutor),用于顺序地执行所有计时器任务。计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,那么它会“独占”计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能“堆在一起”,并且在上述不友好的任务最终完成时才能够被快速连续地执行。

默认情况下,任务执行线程并不作为守护线程 来运行,所以它能够阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,那么调用者应该调用计时器的 cancel 方法。 此类是线程安全的:多个线程可以共享单个 Timer 对象而无需进行外部同步。

 

此类不 提供实时保证:它使用 Object.wait(long) 方法来安排任务。 

实现注意事项:此类可扩展到大量同时安排的任务(存在数千个都没有问题)。在内部,它使用二进制堆来表示其任务队列,所以安排任务的开销是 O(log n),其中 n 是同时安排的任务数。Timer如果异常终止,将会导致此后的其他任务不能被执行(抛出IllegalStateException)。

 

构造器:Timer(boolean isDaemon),实例化timer并制定是否采用守护线程方式。内部同时实例化一个TimerThread的线程,此线程负责从taskerQueue中获取最近需要执行的任务(while循环),对于“重复执行”的任务则首先计算下一次需要执行的时间并重新提交“任务”,然后开始执行task。。如果task抛出异常,将导致TimerThread退出,此后的任务也将不能被执行。

 

  • void schedule(TimerTask,Date)/scheduleAtFixedRate(TimerTask,Date,period)/scheduleAtFixedRate(TimerTask,delay,period):向timer提交任务,内部实现很简单,将任务信息交付给taskQueue。taskQueue是一个重新实现的内部类,使用轻量级的数组实现了一个类似“PriorityQueue”(思想和Scheduler几乎一致),每个新提交(或者重复执行的任务再次调度)的任务都会被按照剩余时间进行正序排列。
  • void cancel():终止定时器,并清空所有已经安排的任务。并将TimerThread标记为“不可接收新任务”(thread.newTasksMayBeScheduled = false;)
  • void purge():遍历整个timer,并移除所有的已经“CANCELED”的task.

七.TimerTask类(abstract)

此类实现了Runnable接口,表明其可以在Thread中执行。此类还有有一个cancel()方法,将此task的状态标记为CANCELD,此后Timer将不会再执行它。

因为Timer的特殊性(区别于Scheduler),期望在run方法中对异常做好全面的控制。以免Timer异常退出。

 

 

八.java.util.zip包:

1) 提供用于读写标准 ZIP 和 GZIP 文件格式的类。

2) 使用 DEFLATE 压缩算法(用于 ZIP 和 GZIP 文件格式)对数据进行压缩和解压缩的类。

3) 用于计算任意输入流的 CRC-32 和 Adler-32 校验和的实用工具类。 

校验和算法-->

Checksum接口:提供校验和操作,此接口的实现,目前有Adler32和CRC32两个类.(Adler32和CRC32是同一类算法,只是Adler32相对更加快捷可靠而已,"循环冗余校验-CRC")

此接口方法列表:

  • long getValue():获取校验和值,64位long型数字.
  • void reset():重置校验和
  • void update(byte[],int off,int len):使用指定字节数组更新校验和
  • void update(int b): 使用指定字节,更新校验和.

由上述方法可以得出,CheckSum具有对不固定长度的流数据,进行校验和计算的能力.这种方式,有助于我们,在数据网络传输时(发送或者接受)都能够对数据行进行校验(包括分段校验)等.

CheckedInputStream/CheckedOutputStream,是基于流操作的校验和辅助类,可以指定相应的IO操作,然后在操作结束后,获取相应的校验和值.底层实现非常简单,使用了CheckSum作为工具.

构造函数:

CheckInputStream(InputStream in,CheckSum checkSum)

CheckOutputStream(OutputStream in,CheckSum checkSum)

这两个类分别继承自FilterInputStream和FilterOutputStream(其实内部并没有太多使用到Filter*Stream的特性).

这两个类,有个比较重要的方法,就是CheckSum getCheckSum():获取校验和类,在进行IO操作结束后,可以获取校验和的值..

Check*Stream类中的,所有对IO的操作方法都会在执行结束后,进行checkSum.update操作.例如:

///CheckInputStream.read
public int read() throws IOException {
    int b = in.read();

    if (b != -1) {
        cksum.update(b);
    }

    return b;
 }

 

.

............................Demo...............
public class CheckSumTestMain {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception{

        // TODO Auto-generated method stub
        String file = "E:\\checksum.txt";
        Checksum cksum = new Adler32();//or new CRC32()
        OutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
        DataOutputStream out = new DataOutputStream(new CheckedOutputStream(bos, cksum));
        String body = "Here is body,Do you know..";
        byte[] bytes = body.getBytes();
        out.writeInt(bytes.length);//write the length of body-content 
        out.write(bytes);//write body
        long ckv = cksum.getValue();
        out.writeLong(ckv);//write checksum to the end of file
        out.close();
        System.out.println("write over!");
        cksum.reset();
        InputStream ios = new BufferedInputStream(new FileInputStream(file));
        DataInputStream in = new DataInputStream(new CheckedInputStream(ios, cksum));
        int rl = in.readInt();
        System.out.println("read length:" + rl);
        byte[] b = new byte[rl];
        in.readFully(b);
        System.out.println("body:" + new String(b));
        System.out.println("current checksum:" + cksum.getValue());//get checksum here.
        System.out.print("file checksum:" + in.readLong());//get file checksum.
        in.close();

    }

}

 

////////其他

MD5:不可逆"内容摘要算法"

SHA-1:内容摘要算法.

SHA-1和MD5都是基于hash,且SHA-1基于MD5算法.这两个算法都是用来将长度不确定的数据,最终生成长度一定的"摘要"(MD5为128位),如果原始数据被改动,那么其"摘要"必将被改变.因此可以用SHA-1或者MD5来校验文件数据/网络数据是否被改动.

CRC32/Adler32也是一种摘要算法,不过这种算法是线性分组码,即文件数据或者/网络数据,将会根据字节的顺序,线性的方式对其ASCII值进行计算(累加或者为运算),最终得到一个64为的数字(校验和),所以字节数据以任何顺序的改动,都会导致最终的校验和不同.

CRC32/Adler32被广泛的用在网络数据传输中.来判断传输的数据是否丢失.

 

九.Pattern和Matcher.

Pattern类:正则表达式编译器.为Pattern指定需要编译的表达式,然后即可匹配相应的字符串;执行匹配锁涉及的所有状态都驻留在匹配器中(Matcher),所以多个匹配器可以共享一个模式(Pattern);可供多个并发线程安全使用.注意Pattern类的构造器为私有的,不能在外部被创建.

  • static Pattern compile(String regex):根据指定的正则字符串,创建Pattern模式;如果表达式无法解析,将抛出异常.
  • static boolean matches(String regex,CharSequence input):根据指定的表达式去匹配input,如果匹配成功则返回true.内部实现为创建Pattern实例,并获取Matcher实例.这是一个便捷的方式.
  • Matcher matcher(CharSequece input):匹配指定的input,返回一个Matcher实例.(每次都会创建一个新的Matcher实例)
  • String[] split(CharSequeue input,int limit)
  • String[] split(CharSequeue input):这两个方法大同小异,将input按照Pattern指定的表达式分割,并返回String数组,limit为匹配的成功截止次数.java.lang.String.split()方法底层使用了此方式.

Matcher是匹配器,根据Pattern(模板)和input,进行顺序化的匹配结果.简单介绍几个方法:

  • boolean find():尝试查找与该模式匹配的输入序列的下一个子序列,如果匹配成功,则返回true,如果到结尾且无匹配成功,则返回失败.
  • String group():获取当前匹配成功的序列(实际字符串,非字面值).
  • String replaceAll(String replacement):根据模式,依次匹配并替换匹配成功的序列片段.java.lang.String.replaceAll()采用的为此实现.
//////Demo
 
    Pattern p = Pattern.compile("[0-9]:");
    Matcher m = p.matcher("1:2:3:4");
    while(m.find()){
    System.out.println(m.group());
    }
    输出结果为:
    1:
    2:
    3:

 

 

你可能感兴趣的:(java)