博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【java基础】集合框架总结
阅读量:2380 次
发布时间:2019-05-10

本文共 2416 字,大约阅读时间需要 8 分钟。

文章目录

前言

ArrayList 和 LinkedList 的区别

  • ArrayList增删的时候在扩容的时候慢,通过索引查询快,通过对象查索引慢

  • 当数组无法容纳下此次添加的元素时进行扩容,扩容之后容量为原来的1.5倍

  • LinkedList 插入,删除都是移动指针效率很高。

  • 查找需要进行遍历查询,效率较低。

  • 内存占用比ArrayList多,因为要存储下一个节点的地址

ArrayList 和 Vector 的区别

  • Vector是线程安全的,源码中有很多的synchronized可以看出,而ArrayList不是。导致Vector效率无法和ArrayList相比;
  • ArrayList和Vector都采用线性连续存储空间,当存储空间不足的时候,ArrayList默认增加为原来的50%,Vector默认增加为原来的一倍;
  • Vector可以设置capacityIncrement,而ArrayList不可以,从字面理解就是capacity容量,Increment增加,容量增长的参数。
  • Vector是一个同步容器,不是一个并发容器!!!

HashMap

  1. JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。针对这种情况,JDK 1.8 中引入了红黑树(查找时间复杂度为 O(logn))来优化这个问题
  2. 为什么线程不安全?多线程PUT操作时可能会覆盖刚PUT进去的值;扩容操作会让链表形成环形数据结构,形成死循环
  3. 容量的默认大小是 16,负载因子是 0.75,当 HashMap 的 size > 16*0.75 时就会发生扩容(容量和负载因子都可以自由调整)。
  4. 为什么容量是2的倍数?在根据hashcode查找数组中元素时,取模性能远远低于与性能,且和2^n-1进行与操作能保证各种不同的hashcode对应的元素也能均匀分布在数组中

HashMap 和 Hashtable 的区别

  1. 线程是否安全: HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过 synchronized修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!);
  2. 效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;
  3. 对Null key 和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛出 NullPointerException。
  4. 初始容量大小和每次扩充容量大小的不同 : ①创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小(HashMap 中的tableSizeFor()方法保证,下面给出了源代码)。也就是说 HashMap 总是使用2的幂作为哈希表的大小,后面会介绍到为什么是2的幂次方。
  5. 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。

HashSet 和 HashMap 的区别

HashSet 的原理比较简单,几乎全部借助于 HashMap 来实现的。

查看源码的 add() 方法。可以看出它是将存放的对象当做了 HashMap 的健,value 都是相同的 PRESENT 对象。由于 HashMapkey 是不能重复的,所以每当有重复的值写入到 HashSet 时,value 会被覆盖,但 key 不会受到影响,这样就保证了 HashSet 中只能存放不重复的元素。

ConcurrentHashMap

更多 HashMap 与 ConcurrentHashMap 相关请查看

HashTable 在每次同步执行时都要锁住整个结构。ConcurrentHashMap 锁的方式是稍微细粒度的。 ConcurrentHashMap 将 hash 表分为 16 个桶(默认值)

JDK1.7

image.png | left | 502x537

ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment。HashEntry 用来封装映射表的键 / 值对;Segment 用来充当锁的角色,每个 Segment 对象守护整个散列映射表的若干个桶。每个桶是由若干个 HashEntry 对象链接起来的链表。一个 ConcurrentHashMap 实例中包含由若干个 Segment 对象组成的数组。

JDK1.8

image.png | left | 781x496

  1. 为进一步提高并发性,放弃了分段锁,使用CAS + synchronized 来保证
  2. put操作:如果Key对应的数组元素为null,则通过CAS操作将其设置为当前值。如果Key对应的数组元素(也即链表表头或者树的根元素)不为null,则对该元素使用synchronized关键字申请锁,然后进行操作。如果该put操作使得当前链表长度超过一定阈值,则将链表(寻址时间复杂度为O(N))转换为红黑树(寻址时间复杂度为O(log(N))

转载地址:http://cvmxb.baihongyu.com/

你可能感兴趣的文章
sar的用法
查看>>
connect by 的排序问题
查看>>
linux oracle AIO实现
查看>>
vmstat详解
查看>>
rman维护归档日志
查看>>
办公室一族喝茶养生:黄芪泡茶使精力旺盛
查看>>
mysql里alter table 重定义主键的步骤:
查看>>
10g和11g自动任务的区别
查看>>
Mysql innodb存储引擎的性能优化
查看>>
vim的列编辑
查看>>
删除表空间,有rman全备的恢复(使用dbms_backup_restore来进行恢复)
查看>>
mysql性能监控指标
查看>>
show engine innodb status 详解
查看>>
关于执行计划里recursive calls,db block gets和consistent gets参数的解释
查看>>
dbms_stats
查看>>
linux手动回收cache
查看>>
memcached安装
查看>>
mysql处理递归的一个例子
查看>>
回收mysql表的碎片
查看>>
fast刷新的限制
查看>>