Arraylist 与 LinkedList 异同
- ArrayList使用的是数组,LinkedList使用的是双向链表。
- 二者都是不同步的,也就是不保证线程安全。
- ArrayList实现了RandomAccess接口(该接口内什么都没定义,只是一个标识,说明实现了该接口的类可以随机访问),支持快速随机访问(
get(int index)
),LinkedList不支持。
ArrayList与Vector区别
- ArrayList是不同步的,线程不安全,Vector同步,线程安全。
- Vector包含许多传统方法,这些方法不属于集合框架。
HashMap
底层实现
JDK1.8之前
JDK1.8之前使用数组加链表实现的,也就是链表散列。将key的hashCode经过扰动函数处理得到hash值,然后通过(n-1) & hash
判断存储的位置(n是数组长度),如果该位置没有存放元素,就放在这里。如果该位置存放元素,判断该位置的元素和要存放的元素的key是否一样,如果一样,直接覆盖,否则,用拉链法解决冲突。
JDK1.8之后
JDK1.8之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
长度为什么是2的幂次方
为了减少碰撞,尽量把数据分配均匀。hash值大概有40亿映射空间,但内存是放不下的,所以要对数组的长度取模运算,也就是hash % length
,计算机中直接求余效率不如位移运算,所以优化为(length-1) & hash
(前提是length是2 的幂次方)。
为什么该算法可以减少碰撞呢
2的n次方实际就是1后面n个0,2的n次方-1 实际就是n个1。
例如长度为9时候,3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了。
例如长度为8时候,3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞。
线程不安全
HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。多线程会造成死循环问题。如果需要满足线程安全,可以用 Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者ConcurrentHashMap。
HashMap 和 Hashtable 的区别
HashTable基本淘汰,不要使用
- HashMap是非线程安全的,HashTable是线程安全的,因为内部方法使用了synchronized修饰。
- HashMap效率比HashTable高一些。
- HashMap中可以有一个键为null,可以有多个键的值为null。HashTable中key和value都不能为null。
- 创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。
- 创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而HashMap 会将其扩充为2的幂次方大小。
- JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。
HashSet 和 HashMap 区别
HashSet 底层就是基于 HashMap 实现的
- HashMap实现了Map接口,HashSet实现了Set接口。
- HashMap储存键值对,HashSet仅仅存储对象。
- 使用put()方法将元素放入map中,使用add()方法将元素放入set中。
- HashMap中使用键(key)来计算hashcode值,HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false。
- HashMap比较快,因为是使用唯一的键来获取对象,HashSet较HashMap来说比较慢。
集合框架底层数据结构总结
Collection
1. List
- ArrayList: Object数组。
- Vector: Object数组。
- LinkedList: 双向链表。
2. Set
- HashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素。
- TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树)。
Map
- HashMap: JDK1.8之前HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。
- HashTable: 线程安全(利用synchronized修饰)。数组+链表组成的,数组是 HashTable 的主体,链表则是主要为了解决哈希冲突而存在的。
- TreeMap: 红黑树(自平衡的排序二叉树)。