6.对比Vector、ArrayList、LinkedList有何区别以及常见的集合问题

第6讲:对比Vector、ArrayList、LinkedList有何区别

典型回答:

相同点:

  • 三者都是实现集合框架中的List,也就是所谓的有序集合,存取有序,有索引,可以重复,具体功能比较相似,都能实现增删改查,都提供迭代器以遍历其内容。

区别:

  • Vector是Java早期提供的线程安全的动态数组,线程安全,增删改查都比较慢。
  • ArrayList底层是数组,线程不安全,查找和修改快,增删慢,使用get和set方法是花费常数时间的,但是如果插入元素和删除元素,除非插入和删除的位置都在表末尾,否则代码开销会很大,因为里面需要数组的移动。与Vector类似,也是可以根据需要调整容量,不过二者的调整逻辑有所区别,Vector在扩容时提高1倍,而ArrayList则是增加50%
  • LinkedList是双向链表实现的,线程不安全,所以get会非常消耗资源,除非位置离头部很近,但是插入和删除元素花费常数时间。

扩展知识

1.集合框架

  • List,有序集合,可重复,增删改查
  • Set,无序不可重复
  • Queue/Deque,除了集合的功能,还支持类似的先入先出(FIFO)或者后入先出(LIFO)
2.Map和Set
  • TreeSet实际上是利用TreeMap实现的,Java类库创建了一个Dummy对象”PRESENT”作为value,然后所有插入的对象是以键的形式放入了TreeMap里面。
  • 同理,HashSet也是以HashMap为基础实现的。
3.Set的一些使用说明
  • TreeSet支持自然顺序访问,但是添加、删除、包含等操作相对要低效(log(n)时间)
  • HashSet则是利用Hash算法,理想情况下,如果哈希散列正常,可以提供常数时间的添加、删除、包含等操作,但是不保证有序
  • LinkedhashSet,内部构建了一个记录插入顺序的双向链表,因此提供了按照插入顺序遍历的能力,于此同时,也保证了常数时间的添加、删除、包含等操作,这些性能略低于HashSet,因为需要维护这些链表的开销。
  • 在遍历列表时,HashSet性能受自身容量的影响,所以初始化时,除非有必要,不然不要将其背后的HashSet容量设置过大,而对于LinkedHashSet,由于其内部链表提供的方便,遍历性能只和元素的多少有关。
4.Collections的synchronized方法
  • Collections工具类中,提供了一系列的synchronized方法,比如:List<T> synchronizedList(List<T> list) ,所以可以用类似的方法来实现基本的线程安全集合:List list =Collections.synchronizedList(new ArrayList()); 其实现就是将每个方法,比如get\set\add之类,都通过synchronized添加同步支持,简单粗暴,但是也非常实用。这些方法创建的线程安全集合,都符合迭代是fail-fast行为,当发生意外的并发修改时,尽早抛出ConcurrentModificationException 异常,以避免不可预期的行为
5.排序
  • 对于原始数据类型,目前使用的是所谓双轴快速排序,是一种改进的快速排序算法,早期版本是相对传统的快速排序
  • 对于对象数据类型,目前则是使用TimSort,思想上也是一种归并和二分插入排序(binarySort)结合的优化排序算法。TimSort 并不是 Java 的独创,简单说它的思路是查找数据集中已经排好序的分区(这里叫 run),然后合并这些分区来达到排序的目的。
6.思考题

先思考一个应用场景,比如你需要实现一个云计算任务调度系统,希望可以保证 VIP 客户的任务被优先处理,你可以利用哪些数据结构或者标准的集合类型呢?更进一步讲,类似场景大多是基于什么数据结构呢?

  • 自然就会想到优先级队列了,但还需要额外考虑vip再分级,即同等级vip的平权的问题,所以应该考虑除了直接的和vip等级相关的优先级队列优先级规则问题,还得考虑同等级多个客户互相不被单一客户大量任务阻塞的问题。
  • 其实我觉得应该参考银行窗口,同时三个窗口,就是三个队列,银台就是消费者线程,某一个窗口vip优先,没有vip时也为普通客户服务。要实现,要么有个dispatcher,要么保持vip通道不许普通进入,vip柜台闲时从其他队列分配过来普通客户

猜你喜欢

转载自blog.csdn.net/endlessseaofcrow/article/details/80425812