第一,简介
这三者都是实现集合框架中的List,也就是所谓的有序集合,因此具体功能也比较近似,比如都提供按照位置进行定位,添加或者删除的操作,都提供迭代器以遍历其内容等。但因为具体的设计区别,在性能,行为,线程安全等方面,表现又有很大不同。
Vector 是 java 早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector内部是使用对象数组来保存数据,可以根据需要自动的增加容量,当数组已满时,会创建新的数组,并拷贝原有数组数据。
ArrayList 是线程不安全的动态数组实现的。ArrayList 也是根据需要调整容量,ArrayList 是每次增加 50%,Vector 是每次增加1倍。
LinkedList 是线程不安全双向链表实现的。所以它不需要调整容量。
java 的集合框架,Collection 接口是所有集合的根,它扩展提供了三大类集合,分别是:1,List 提供了方便的访问,插入,删除等操作。2,Set 是不允许重复元素,这是和 List 最大的区别,3,Queue/Deque 是标准队列结构的实现,支持先入先出或者后入先出。这里不包括BlockingQueue,因为通常是并发编程场合,所以防止在并发包里。
每种集合的通用逻辑,都被抽象到相应的抽象类中,比如 AbstractList 就集中了各种 List 操作的通用部分。这些集合不是完全孤立的,比如 LinkedList 既是 List 又是 Deque 。
看下图:
第二,应用场景
Vector 和 ArrayList 作为动态数组,其内部元素以数组形式顺序存储。所以非常适合随机访问的场合。除了尾部插入和删除元素,其他行为往往性能会相对较差。LinkedList 进行节点插入,删除却要高效的多,但是随机访问性能则要比动态数组慢。所以在开发中如果偏向于插入,删除使用 LinkedList ,如果是随机访问较多使用 Vector 和 ArrayList 。
阅读源码后就会发现,TreeSet 代码里实际默认是利用 TreeMap 实现的,Java 类库创建了一个Dummy 对象 “PRESENT” 作为 Value,然后所有插入的元素其实是以键的形式放入了 TreeMap 里面;同理,其实 HashSet 也是以 HashMap 基础实现的,它们都是 Map 类的马甲。以 Set 的几个实现为例:1,TreeSet 支持自然顺序访问,但是添加,删除,包含等操作要相对低效。2,HashSet 则是利用哈希算法,理想情况下,如果哈希散列正常,可以提供常数时间的添加,删除,包含等操作,但是它不保证有序,。3,LinkedHashSet 内部构建了一个记录插入顺序的双向链表,因此提供了按照插入顺序遍历的能力,与此同时,它也提供常数时间的添加,删除,包含等操作。这些操作性能略低于 HashSet,因为需要维护链表的开销。4,遍历元素时,HasSet 性能受自身容量影响,所以初始化除非必要,不然不要将其背后的 HashMap 容量设置过大。而对于 LinkedHashSet,由于其内部链表提供的方便,遍历性能和元素多少有关系。
在 Collections 工具类中,提供了一系列的 synchronized 方法,比如:static <T> List<T> synchronizedList(List<T> list);我们完全可以利用类似的方法实现基本的线程安全集合:List list = Collections.synchronizedList(new ArrayList());它的实现就是简单的将每个基本方法通过 synchronized 添加同步支持,非常简单粗暴也非常实用。
Java9 中,提供了一系列静态工厂方法可以提供不可变集合对象,比如,List.of(),Set.of();例子:List<String> simpleList = List.of ("Hello","world");它的特点是:1,集合对象不可变,线程安全。2,不需要扩容,所以空间上更加紧凑。
网友评论