典型回答
这三者都是实现集合框架中的 List,也就是所谓的有序集合,提供相似的操作,因为具体的设计区别,在行为、性能、线程安全等方面,表现又有很大不同。
Vector: 线程安全得动态数组,内部是使用对象数组来保存数据,可以根据需要自动的增加容量,当数组已满时,会创建新的数组,并拷贝原有数组数据。
ArrayList: 应用更加广泛的动态数组实现,线程不安全,性能好,Vector 在扩容时会提高 1 倍,而 ArrayList则是50%。
LinkedList: 双向链表,线程不安全。
适用场景
Vector 和 ArrayList 作为动态数组,其内部元素顺序存储,所以非常适合随机访问的场合。插入和删除元素(除了尾部)需要移动后续所有元素,性能较差。
LinkedList 进行节点插入、删除却要高效得多,但随即访问性能较差。
在应用开发中,如果事先可以估计到,应用操作是偏向于插入、删除,还是随机访问较多,就可以针对性的进行选择。
狭义的集合框架(不包括Map)
TreeMap/TreeSet 支持自然顺序/自定义顺序,但是添加、删除、包含等操作要相对低效(log(n) 时间)
HashMap/HashSet 利用哈希算法,可以提供常数时间的添加、删除、包含等操作,但是它不保证有序。
LinkedHashMap/LinkedHashSet,内部构建了一个记录插入顺序的双向链表,因此提供了按照插入顺序遍历的能力,也保证了常数时间的变更操作,这些操作性能略低于HashMap,因为维护链表的开销。
以上集合都符合迭代时 fail-fast 行为,当发生意外的并发修改时,尽早抛出 ConcurrentModificationException 异常,以避免不可预计的行为。
在遍历元素时,HashMap 性能受自身容量影响,所以初始化,除非有必要,不然不要将其背后的 HashMap 容量设置过大。LinkedHashSet,由于其内部链表提供的方便,遍历性能只和元素多少有关系。
对于线程不安全的集合,可以利用Collections 工具类中,提供了一系列的 synchronized方法,例如
List list = Collections.synchronizedList(new ArrayList());
实现原理是所有访问方法通过synchronizd 添加基本的同步支持,简单粗暴。
Arrays.sort()的排序算法
- 对于原始数据类型,目前使用的是所谓双轴快速排序(Dual-Pivot QuickSort),是一种改进的快速排序算法。
- 对于对象数据类型,目前则是使用TimSort,思想上也是一种归并和二分插入排序(binarySort)结合的优化排序算法。
Java9 集合类提供了一系列静态方法,例如,List.of()、Set.of(),大大简化了构建小的容器实例的代码量。根据业界实践经验,我们发现相当一部分集合实例都是容量非常有限的,而且在生命周期中并不会进行改变。
// 一句代码创建list,且是immutable
List<String> simpleList = List.of("Hello","world");