Vector、ArrayList、LinkedList 什么关系

总结

这三者都是实现集合框架中的List,也就是所谓的有序集合,因此具体功能也比较近似,比如都提供按照位置进行定位、添加或者删除的操作,都提供迭代器以遍历其内容等。但因
为具体的设计区别,在行为、性能、线程安全等方面,表现又有很大不同。

Vector是Java早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同步是有额外开销的。Vector内部是使用对象数组来保存数据,可以根据需要自动的增加
容量,当数组已满时,会创建新的数组,并拷贝原有数组数据。

ArrayList是应用更加广泛的动态数组实现,它本身不是线程安全的,所以性能要好很多。与Vector近似,ArrayList也是可以根据需要调整容量,不过两者的调整逻辑有所区
别,Vector在扩容时会提高1倍,而ArrayList则是增加50%。
LinkedList顾名思义是Java提供的双向链表,所以它不需要像上面两种那样调整容量,它也不是线程安全的。

扩展

场景

  • Vector和ArrayList作为动态数组,其内部元素以数组形式顺序存储的,所以非常适合随机访问的场合。除了尾部插入和删除元素,往往性能会相对较差,比如我们在中间位置插入一个元素,需要移动后续所有元素。
  • 而LinkedList进行节点插入、删除却要高效得多,但是随机访问性能则要比动态数组慢。

设计结构

  • Collection 接口时所有集合的跟
  • List 有序集合,它提供了方便的访问、插入、删除等操作。
  • Set 不允许重复元素的,这是和List最明显的区别,也就是不存在两个对象equals返回true
  • Queue/Deque 标准队列实现结构,拥有集合的基本功能,还有一 FIFO 和 LIFO 特定行为

每种集合的逻辑都被抽象到相呼应的抽象集合,比如 AbstractList 集中了 List 操作通用部分。并且每集合不是孤立的,比如 LinkedList 既是 List,也是 Deque。

Queue/Deque 几个实现

  • PriorityQueue 优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序,对于自己定义的类来说,需要自己定义比较器
  • ArrayDeque大下可变的数组双端队列,不允许插入null。

Set 结构的几个实现

  • TreeSet 支持自然顺序访问,但是添加、删除、包含等操作要相对低效(log(n)时间)
  • HashSet 则是利用哈希算法,理想情况下,如果哈希散列正常,可以提供常数时间的添加、删除、包含等操作,但是它不保证有序
  • LinkedHashSet 内部构建了一个记录插入顺序的双向链表,提供了按照插入顺序遍历的能力,同时,也保证了常数时间的添加、删除、包含等操作,这些操作性能略低于HashSet,因为需要维护链表的开销

虽然线程不安全,但是 Collection 工具提供了一系列 synchronized 方法,实现基本线程安全集合

List list = Collections.synchronizedLis(new ArrayLis());

实现就是将每个基本方法通过 synchronizd 添加基本的同步支持,非常简单。

默认排序算法

Array.sort()

  • 原始数据类型,使用双轴快速排序算法,一种改进的快排。早期是相对传统的快排。
    • 太小的数据集,Java会直接进行二分插入排序
  • 对象数据类型,使用 TimSort,一种归并和二分插入排序结合优化算法。的思路是查找
    数据集中已经排好序的分区(这里叫run),然后合并这些分区来达到排序的目的。

Collections.sort()

底层是调用 Array.sort()

另外

java 8 引入并行排序,利用现代多核处理器,底层实现基于 fork-join 框架。

其他新特性

在Java 9中,Java标准类库提供了静态工厂方法,比如,List.of()、Set.of(),简化了构建小的容器实例的代码量。根据业界实践经验,发现相当一部分集合实例都是容量非常有限的,而且在生命周期中并不会进行修改。

在原有的Java类库中,我们可能不得不写成:

ArrayList<String> list = new ArrayList<>();
list.add("Hello");
list.add("World");

容器静态工厂方法,一句代码就够了,并且保证了不可变性。

List<String> simpleLis = List.of("Hello","world");

它是不可变的,符合我们对线程安全的需求;它因为不需要考虑扩容,所以空间上更加
紧凑等。

of方法的源码,会发现一个特别有意思的地方:我们知道Java已经支持所谓的可变参数(varargs),但是官方类库还是提供了一系列特定参数长度的方法,看起
来似乎非常不优雅,为什么呢?这其实是为了最优的性能,JVM在处理变长参数的时候会有明显的额外开销。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值