Vector、ArrayList、LinkedList有何区别 以及 集合框架的知识梳理

Vector、ArrayList、LinkedList有何区别 以及 集合框架的知识梳理

一、考点分析

  • Java集合框架的设计结构,至少要有一个整体印象
  • Java提供的主要容器(集合和Map)类型,了解或掌握对应的数据结构,算法,思考具体技术选择
  • 将问题扩展到性能,并发等领域
  • 集合框架的演进和发展。
  • 数据结构和算法是基本功
    • 内部排序:归并排序,交换(冒泡,快排)排序,选择排序,插入排序
    • 外部排序:掌握利用内存和外部存储处理超大数据集,至少要理解过程和思路
    • 算法稳定性分析

二、集合框架

1、Vector、ArrayList、LinkedList的区别

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

Vector:

  • Vector是Java早期提供的线程安全的动态数组,如果不需要线程安全,并不建议选择,毕竟同
步是有额外开销的。Vector内部是使用对象数组来保存数据

,可以根据需要自动的增加容量,
当数组已满时,会创建新的数组,并拷贝原有数组数据

ArrayList:

  • ArrayList是应用更加广泛的动态数组实现,它本身不是线程安全的,所以性能要好很多。与
Vector近似,ArrayList也是可以根据需要调整容量,不过两者的调整逻辑有所区别,Vector
扩容时会提高1倍,而ArrayList则是增加50%

LinkedList:

  • LinkedList顾名思义是Java提供的双向链表,所以它不需要像上面两种那样调整容量,它也不
是线程安全的。
2、集合框架的整体设计

在这里插入图片描述
List

  • 有序集合,它提供了方便的访问、 插入、删除等操作。

Set:

  • Set是不允许重复元素的,这是和List最明显的区别,也就是不存在两个对象equals
返回true,我们在日常开发中有很多需要保证元素唯一的场合。

  • TreeSet支持自然顺序访问,但是添加、删除、包含等操作要相对低效(log(n)时间)。

  • HashSet则是利用哈希算法,理想情况下,如果哈希散列正常,可源供常数时间的添加、
删除、包含等操作,但是它不保证有序。

  • LinkedHashSet,内部构建了一个记录插入顺序的双向链表,因此提供了按照插入顺序遍历
的能力, 与此同时,也保证了常数时间的添加、删除、包含等操作,这些操作性能略低于
HashSet,因为需要维护链表的开销。

Queue/Deque:

  • 则是Java提供的标准队列结构的实现,除了集合的基本功能,它还支持类
似先入先出(FIFO , First-in-First-Out)或者后入先出(LIFO , Last-In-First-Out)
行为。这里不包括BlockingQueue ,因为通常是并发编程场合,所以被放置在并发包里。

Map:(不属于集合框架)

  • TreeSet代码里实际默认是利用TreeMap实现的,
Java类库创建了一个Dummy对象“PRESENT”作为value ,然后所有插入的元素其实是以键
的形式放入了 TreeMap里面;同理,HashSet其实也是以HashMap为基础实现的,原来他
们只是Map类的马甲!

  • HashMap和TreeMap的区别

    hashMap:

    • HashMap:HashMap是基于散列函数,以数组和链表的方式来存储key/value线程非安全,允许null作为key和value,key不可以重复,value允许重复。
    • 使用HashMap,如果key是自定义的类,就必须重写hashcode()和equals()
    • HashMap中的比较key是这样的,先求出key的hashcode(),比较其值是否相等,若相等再比较equals(),若相等则认为他们是相等的。若equals()不相等则认为他们不相等。
    • HashMap默认初始容量16,加载因子0.75,扩容为旧容量乘2,查找元素快,如果key一样则比较value,如果value不一样,则按照链表结构存储value,就是一个key后面有多个value;

    TreeMap:

    • 基于红黑二叉树的NavigableMap的实现,线程非安全。
    • key不可以重复,value允许重复,存入TreeMap的元素应当实现Comparable接口或者实现Comparator接口,会按照排序后的顺序迭代元素,两个相比较的key不得抛出classCastException
    • 主要用于存入元素的时候对元素进行自动排序,迭代输出的时候就按排序顺序输出。

备注:

  • 每种集合的通用逻辑,都被抽象到相应的抽象类之中,比如AbstractList就集中了各种List操
作的通用部分。

  • 这些集合不是完全孤立的,比如,LinkedList本身,既是List, 也是Deque
哦。

3、如何使集合线程安全
  • 除了java.util.concurrent里面的线程安全容
器,在
Collections工具类中,提供了一系列的synchronized方法,比如

    static <T>  List<T> synchronizedList(List<T> list)
    
    List list = Collections.synchronizedList(new ArrayList());
    
  • 它的实现,基本就是将每个基本方法,比如get、set、add之类,都通过synchronizd添加基本的同步支持,非常简单粗暴,但也非常实用。注意这些方法创建的线程安全集合,都符合迭代
时fail-fast行为(**fail-fast 机制是java Collection中的一种错误机制。**当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。),当发生意外的并发修改时,尽早抛出ConcurrentModificationException异
常,以避免不可预计的行为。

3、集合框架的演进

排序算法:

  • Java 8引入了并行排序算法(直接使用parallelSort方法),这是为了充分利用现代多核多处理器的计算能力,底层实现基于fork-join框架, 当处理的数据集比较小的时候,差距不明显, 甚至表现差一点;但是,当数据集增长
数万或百万以上时,提高就非常大了,具体还是取决于处理器和系统环境。

集合框架演进:

  • 在Java 8之中,Java平台支持了 Lambda和Stream ,相应的Java集合框架也进行了大范围
的增强,以支持类似为集合创建相应stream或者parallelstream的方法实现,我们可以非常
方便的实现函数式代码。链式编程

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

    ArrayList<String> list = new ArrayList<>();
    list.add("Hello");
    list.add("World");
    
    List<String> simpleList = List.of("Hello","world");
    

    而利用新的容器静态工厂方法,一句代码就够了 ,并且保证了不可变性,线程安全。又因为不需要考虑扩容,所以空间上更加紧凑。

三、课后题

**Q:**比如
你需要实现一个云计算任务调度系统,希望可以保证VIP客户的任务被优先处理,你可以利用
哪些

结构或者标准的集合类型呢?类似场景大多是基于什么

结构呢?

A:在这个题目下,自然就会想到优先级队列(堆)了,但还需要额外考虑vip再分级,即同等级vip的
平权的问题,所以应该考虑除了直接的和vip等级相关的优先级队列优先级规则问题还得考
虑同等级多个客户互相不被单一客户大量任务阻塞的问题,数据结构确实是基础,即便这个
思考题考虑的这个场景,待调度数据估计会放在redis里面吧

四、参考文档

  • 极客时间《Java核心技术36讲》第8讲
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值