Java集合

文章目录

1.常见的集合

Java集合类主要由两个根接口CollectionMap派生出来的,Collection派生出了三个子接口:List、 Set、Queue(Java5新增的队列),因此Java集合大致也可分成List、Set、Queue、Map四种接口体系。

注意:

  • Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。
  • Collections 是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法:Collections. sort(list)。
  • Map不是Collection的子接口。

Java集合框架图如下:

 

Collection:

  • List
  • ArrayList
  • LinkedList
  • Vector
  • Stack
  • Set
  • HashSet
  • LinkedHashSet
  • TreeSet

Map:

  • HashMap
  • LinkedHashMap
  • TreeMap
  • ConcurrentHashMap
  • Hashtable

2.线程安全的集合有哪些?线程不安全的呢?

线程安全的:

  • Hashtable:比HashMap多了个线程安全。
  • ConcurrentHashMap:是一种高效但是线程安全的集合。
  • Vector:比Arraylist多了个同步化机制。
  • Stack:栈,也是线程安全的,继承于Vector。

 线性不安全的:

  • HashMap
  • Arraylist
  • LinkedList
  • HashSet
  • TreeSet
  • TreeMap

3. Arraylist与 LinkedList 异同点?

  • 是否保证线程安全:
    • ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全
  • 底层数据结构:
    • Arraylist 底层使用的是Object数组;
    • LinkedList 底层使用的是双向循环链表数据结构;
  • 插入和删除是否受元素位置的影响:
    • ArrayList 采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。 
    • LinkedList 采用链表 存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似 O(1)而数组为近 似 O(n)。
  • 是否支持快速随机访问:
    • LinkedList 不支持高效的随机元素访问,
    • 而ArrayList支持随机访问功能。
  • 内存空间占用:
    • ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间
    •  LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。

4. ArrayList 与 Vector 区别?

线程安全:

  • Vector是线程安全的,Vector在关键性的方法前面都加了 synchronized关键字,来保证线程的安全性,如果有多个线程会访问到集合,那最好是使用 Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
  • ArrayList不是线程安全的。

 扩容机制:

  • ArrayList在底层数组不够用时在原来的基础上扩展0.5倍
  • Vector是扩展1倍,这样ArrayList就有利于节约内存空间。

5. 各种集合的扩容机制汇总

5.1 ArrayList和Vecror 的扩容机制?

  • ArrayList扩容的本质就是计算出新的扩容数组的size后实例化,并将原有数组内容复制到新数组中去。 默认情况下,新的容量会是原容量的1.5倍。
  • Vector是扩展2倍

5.2 LinkedList没有扩容机制 

没有扩容机制,因为其底层是双向链表结构。不存在数组的扩容一说,没有初始化大小,也没有扩容的机制

5.3 HashSet和HashMap扩容机制

HashSet和HashMap都是默认初始容量是16(jdk1.7的),但是jdk1.8做了优化,初始容量为0,第一次存元素的时候才扩容为16,加载因子是0.75,扩容为原来的2倍

而带LinkedHashSetLinkedHashMap是链表不存在扩容的
 

5.4 StringBuffer和StringBuilder的扩容机制

StringBuilder和StringBuffer的初始容量都是16,默认数组容量扩充为原数组容量的2倍+2

6. Array 和 ArrayList 有什么区别?什么时候该应 Array 而不是 ArrayList 呢?

  • Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型。 
  • Array 大小是固定的,ArrayList 的大小是动态变化的。
  • ArrayList 提供了更多的方法和特性,比如:addAll(),removeAll(),iterator() 等等。

7. HashMap的底层数据结构是什么?

在JDK1.7 和JDK1.8 中有所差别:

  • 在JDK1.7 中,由“数组+链表”组成,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在 的。
  • 在JDK1.8 中,由“数组+链表+红黑树”组成。当链表过长,则会严重影响 HashMap 的性能,红黑树搜索 时间复杂度是 O(logn),而链表是糟糕的 O(n)。因此,JDK1.8 对数据结构做了进一步的优化,引入了红 黑树,链表和红黑树在达到一定条件会进行转换:
    • 当链表超过 8 且数据总量超过 64 才会转红黑树。
    • 将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不 是转换为红黑树,以减少搜索时间。

8. 解决hash冲突的办法有哪些?HashMap用的哪种?

解决Hash冲突方法有:

  • 开放定址法
  • 再哈希法
  • 链地址法(拉链法)
  • 建立公共溢出区

HashMap中采 用的是 链地址法

9. 为什么在解决 hash 冲突的时候,不直接用红黑树?而选择先用链表,再转红黑树?

因为红黑树需要进行左旋,右旋,变色这些操作来保持平衡,而单链表不需要。当元素小于 8 个的时 候,此时做查询操作,链表结构已经能保证查询性能。当元素大于 8 个的时候, 红黑树搜索时间复杂度 是 O(logn),而链表是 O(n),此时需要红黑树来加快查询速度,但是新增节点的效率变慢了。 因此,如果一开始就用红黑树结构,元素太少,新增效率又比较慢,无疑这是浪费性能的。

10.HashMap 的put方法流程?

以JDK1.8为例,简要流程如下:

  1. 首先根据 key 的值计算 hash 值,找到该元素在数组中存储的下标;
  2. 如果数组是空的,则调用 resize 进行初始化;
  3. 如果没有哈希冲突直接放在对应的数组下标里;
  4. 如果冲突了,且 key 已经存在,就覆盖掉 value;
  5. 如果冲突后,发现该节点是红黑树,就将这个节点挂在树上;
  6. 如果冲突后是链表,判断该链表是否大于 8 ,如果大于 8 并且数组容量小于 64,就进行扩容;如 果链表节点大于 8 并且数组的容量大于 64,则将这个结构转换为红黑树;否则,链表插入键值 对,若 key 存在,就覆盖掉 value。

 

11.HashSet 和 HashMap 区别?

HashMapHashSet
实现了Map接口实现了Set接口
存储键值对存储对象
HashMap使用键(Key)计算Hashcode

HashSet使用成员对象来计算hashcode,

对于两个对象来说hashcode可能相同,

所以equals()方法来判断对象的相等性,

如果两个对象不同的话,那么返回false

HashMap相较于HashSet较快,因为他使用唯一的键获取对象较慢

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值