在 JDK 1.2 之前,Collections是独立类库,不是 JDK/JRE 中的一部分。当时synchronized性能特别差,很多场景不需要使用同步方式,所以,独立类库的开发者删除了同步操作,这个应该就是ArrayList的前身。
一、Java中Vector和SynchronizedList的区别
有了Vector为什么还要有SynchronizedList
这个问题的答案是从 StackOverflow 中找到的。
在 JDK 1.2 之前,Collections是独立类库,不是 JDK/JRE 中的一部分。当时synchronized性能特别差,很多场景不需要使用同步方式,所以,独立类库的开发者删除了同步操作,这个应该就是ArrayList的前身。但是,少部分场景还是需要使用同步,于是就有了SynchronizedList,一个可以包装所有List子类的包装类,这个类在几乎所有方法上都加上了synchronized同步,这个设计与Vector相似。
古人说“文人相轻”,其实在编码界也是有鄙视链的。在这里就是:虽然我的设计和你的设计类似,但是我的设计就是比你的好。不过,Collections确实设计更优。
一个SynchronizedList实现所有List的同步
SynchronizedList定位是包装类,可以包装所有List的子类。也就是说,无论是ArrayList还是LinkedList都能过实现同步,完全不会修改底层数据结构,既实现的同步,又保留了底层接口的优点。比如LinkedList的插入、删除效率,ArrayList的顺序读取。而且,一个包装类就解决所有List子类的同步需求,完全不需要重复实现一遍。
相对而言,Vector就比较霸道了,任何想要同步的队列,都需要转换为Vector的数组结构。大家都知道,数组存储需要连续空间,顺序读取效率表现优异,但是插入和删除效率就比较差了。
总结
- Vector内部结构是数组,与Collections.synchronizedList(new ArrayList())类似。
- Vector可以指定扩容大小,默认是扩容到原数组长度的 2 倍;ArrayList不能指定扩容大小,直接扩容到原数组大小的 1.5 倍。
- SynchronizedList是一个包装类,可以将List子类都包装为同步队列,从非线程安全队列转为线程安全队列,没有性能延迟,直接包装即可;Vector是一个基于数组的同步队列,其他队列想要转换为Vector,需要有数据拷贝。
- SynchronizedList的迭代器没有做同步,需要用户自己实现;Vector的迭代器做好了同步,开发人员不需要关心同步。
- Vector至今未标记Deprecated,而且随着 JDK 发布,也在更新实现。虽然 JDK 承诺兼容,但是一直没有标记过期,其用意不得而知。
延伸阅读:
二、什么是default方法
Java 8 发布以后,可以给接口添加新方法,但是,接口仍然可以和它的实现类保持兼容。这非常重要,因为你开发的类库可能正在被多个开发者广泛的使用着。而Java 8之前,在类库中发布了一个接口以后,如果在接口中添加一个新方法,那些实现了这个接口的应用使用新版本的接口就会有崩溃的危险。
有了Java 8,是不是就没有这种危险了?答案是否定的。
给接口添加default方法可能会让某些实现类不可用。
让我们看下default方法的细节。
在Java 8中,接口中的方法可以被实现(Java8中的static的方法也可以在接口中实现,但这是另一个话题)。接口中被实现的方法叫做default方法,用关键字default作为修饰符来标识。当一个类实现一个接口的时候,它可以实现已经在接口中被实现过的方法,但这不是必须的。这个类会继承default方法。这就是为什么当接口发生改变的时候,实现类不需要做改动的原因。