Map接口
实现类 | 是否重复 | 数据是否有序 | 是否能存储null | 需要了解 |
---|---|---|---|---|
HashMap | key不重复 | 插入无序 | key,value都可以为null,线程不安全 | 哈希表、散列码、哈希冲突、链地址法、红黑树 |
LinkedHashMap | key不重复 | 插入有序 ,线程安全 | key,value都可以存储null | header、accessOrder |
TreeMap | key不重复 | 数据按key升序或降序 | key不为null,value可以为null | 红黑树 |
WeakHashMap | 只要进行GC,就会对WeakHashMap进行一次回收 | |||
HashTable | key不重复 | key,value都不能为空,线程安全 | - | 已淘汰 |
1.HashMap
HashMap<K,V> extends AbstractMap <K,V> implements Map<K,V>
HashMap的一些重要属性
//默认初始桶容量The default initial capacity - MUST be a power of two.
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //16
默认最大容量:
static final int MAXIMUM_CAPACITY = 1 << 30;
加载因子0.75f
//当 HashMap中键值对的数量超过数组大小 loadFactor时,就会进行数组扩容。*
static final float DEFAULT_LOAD_FACTOR = 0.75f;
transient Node<K,V>[] table; //桶数组
transient Set<Map.Entry<K,V>> entrySet;
transient int size;
HashMap的构造方法(总共四种)
public HashMap(int initialCapacity, float loadFactor);
public HashMap(int initialCapacity);
public HashMap();
public HashMap(Map<? extends K, ? extends V> m);
HashMap的一些常用方法
static final int hash(Object key)
public int size()
public boolean isEmpty()
public V get(Object key)
final Node<K,V> getNode(int hash, Object key)
public boolean containsKey(Object key)
public boolean containsValue(Object value)
public V put(K key, V value)
public void putAll(Map<? extends K, ? extends V> m)
public V remove(Object key)
public boolean remove(Object key, Object value)
public void clear()???
public Set<Map.Entry<K,V>> entrySet();
public boolean replace(K key, V oldValue, V newValue)
public V replace(K key, V value)
public Object clone()
静态内部类
static class Node<K,V> implements Map.Entry<K,V>
final int hash;
final K key;
V value;
Node<K,V> next;
…
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
- HashMap插入无序,输出也无序,底层采用数组+链表+红黑树实现,不管是插入还是输出,都是根据桶的数组下标依次进行插入或输出。
2.LinkedHashMap
LinkedHashMap <K,V> extends HashMap<K,V> implements Map<K,V>
LinkedHashMap的一些重要属性
transient LinkedHashMap.Entry<K,V> head;
transient LinkedHashMap.Entry<K,V> tail;
//LinkedHashMap通过双向链表实现数据插入有序
final boolean accessOrder; //accessOrder默认值为false 当设置为true时表示访问有序
LinkedHashMap <Integer,Integer> linkedHashMap = new LinkedHashMap<Integer,Integer>(16,0.75f,true);
linkedHashMap.put(5,5);
linkedHashMap.put(2, 2);
linkedHashMap.put(1, 1);
linkedHashMap.put(6, 6);
Iterator<Map.Entry<Integer, Integer>> iterator2 = linkedHashMap.entrySet().iterator();
//输出为5,2,1,6 LinkedHashMap插入有序
while(iterator2.hasNext()) {
System.out.print(iterator2.next().getKey()+" ");
}
linkedHashMap.get(2); //5,1,6,2
linkedHashMap.get(6); //5,1,2,6
//再用迭代器输出,顺序为5,1,2,6 原因:访问有序
Iterator<Map.Entry<Integer, Integer>> iterator3 = linkedHashMap.entrySet().iterator();
while(iterator3.hasNext()) {
System.out.print(iterator3.next().getKey()+" ");
}
静态内部类
static class Entry<K,V> extends HashMap.Node<K,V>{
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
//LinkedHashMap的Entry<K,V> 继承自HashMap的Node<K,V>
//HashMap的Entry<K,V>继承自Map的Entry<K,V>
//所以它们俩最终都继承自Map的Entry<K,V>
LinkedHashMap的构造方法(共五种,前四种调用父类HashMap的构造方法)
public LinkedHashMap(int initialCapacity, float loadFactor); //加载因子继承自HashMap 默认为0.75f
public LinkedHashMap(int initialCapacity);
public LinkedHashMap();
public LinkedHashMap(Map<? extends K, ? extends V> m);
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) //accessOrder默认为false
LinkedHashMap的一些常用方法
//LinkedHashMap中只对这三种方法进行了修改(为什么没有@Override?? )
public boolean containsValue(Object value)
public V get(Object key)
public void clear()
- LinkedHashMap是如何实现数据插入有序的??
/*
当新增一个结点p时,tail指向p,last指向p的上一个节点,
若last为空,说明原来的集合是空的,head也指习向p
否则,p的bofore指向last,last的after指向p
这样就实现了双向链表功能,保证数据插入有序
*/
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p);
return p;
}
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
3.TreeMap
TreeMap<K,V> extends AbstractMap<K,V>
TreeMap中的一些属性
private transient Entry<K,V> root; //root为红黑树的根节点
TreeMap的构造方法(共四种)
public TreeMap();
public TreeMap(Comparator<? super K> comparator);
public TreeMap(Map<? extends K, ? extends V> m);
public TreeMap(SortedMap<K, ? extends V> m);
TreeMap中的一些方法
public boolean containsKey(Object key)
public boolean containsValue(Object value)
public V get(Object key)
public K firstKey()
public K lastKey()
public void putAll(Map<? extends K, ? extends V> map)
final Entry<K,V> getEntry(Object key)
public V put(K key, V value)
public V remove(Object key)
public void clear()
public boolean replace(K key, V oldValue, V newValue)
public V replace(K key, V value)
TreeMap的Entry结点
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left; //左孩子
Entry<K,V> right; //右孩子
Entry<K,V> parent; //父节点
boolean color = BLACK; //该节点的颜色
...
}
/*从Entry节点可以看出,TreeMap使用红黑树的结构,实现数据的有序排列*/
- 自定义实现升序或降序排序
TreeMap<Integer,String> tm = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
//return o1-o2;升序排列
return o2-o1; //降序排列
}
});
//接口可以通过匿名内部类的方式创建实例并实现接口中的方法
4.WeakHashMap
略(●’◡’●)
List接口
实现类 | 特点 | 应用场景 |
---|---|---|
ArrayList | 数据可以重复,数据插入无序,可以存储null | 查询多,修改少 |
LinkedList | 数据可以重复,数据插入有序,可以存储null | 查询少,修改多 |
- 访问效率:对于get和set方法,ArrayList优于LinkedList
- 修改效率:对于add和remove方法,LinkedList优于ArrayList
1.ArrayList
- ArrayList和Vector的区别:
ArrayList | Vector |
---|---|
效率相对高 | 效率相对低 |
线程不安全 | 线程安全 |
-
ArrayList的默认初始大小是10 默认扩容1.5倍
-
从modCount了解快速失败(fast-fail)机制:能够立刻报告失败的错误检测机制
在java中,构造迭代器对象时,初始化expectedModCount=modCount 。 在迭代过程中,当ArrayList进行add或者remove操作时,modCount会发生改变,而expectedModCount没有发生改变,这是二者就不相等,于是抛出异常。
这种机制不允许在迭代过程中修改集合。 -
Non-Fast-Fail机制:允许在迭代过程中修改集合,并且不会抛出异常。
CopyOnWriteArrayList在迭代过程中不会抛出异常。 -
以ArrayList为例,对Iterator的进行分析
当cursor>=集合对象length时,抛出异常:
throw new ConcurrentModificationException();
当modCount!=expectedModCount时,抛出异常:
throw new ConcurrentModificationException();
这个异常叫做并发的修改异常
为什么会出现这个异常呢?
多线程也会发生这种问题,假设当一个线程正在迭代,另一个线程修改了值。
要想解决这个问题,对单线程来说,如果想remove,就用iterator进行remove
对多线程来说,创建线程安全的容器:
Collections.synchronizedList(list);
2.LinkedList
Set接口
实现类 | 特点 | 应用场景 |
---|---|---|
HashSet | 数据无序,不能重复,能存储null | 数据去重 |
LinkedHashSet | 数据有序,不能重复,能存储null | 数据去重、插入有序 |
TreeSet | 数据从小到大或从大到小排序,不能重复,不能存储null | 数据去重、按特定大小排序 |
1.HashSet
public class HashSet extends AbstractSet implements Set…
HashSet中的一些属性
private transient HashMap<E,Object> map;
HashSet的构造方法(共五种)
public HashSet(){
map = new HashMap<>();
}
//HashSet底层是通过HashMap实现的
public HashSet(Collection<? extends E> c)
public HashSet(int initialCapacity, float loadFactor)
public HashSet(int initialCapacity)
HashSet(int initialCapacity, float loadFactor, boolean dummy)
HashSet的一些方法
public int size()
public boolean isEmpty()
public boolean contains(Object o)
public boolean add(E e)
public boolean remove(Object o)
public void clear()
2.LinkedHashSet
public class LinkedHashSet extends HashSet implements Set…
- 构造方法调用父类的构造方法
- 没有新的函数
3.TreeSet
public class TreeSet extends AbstractSet…
TreeSet的构造方法(共四种)
public TreeSet() {
this(new TreeMap<E,Object>());
}
//TreeSet底层是通过TreeMap实现的
public TreeSet(Comparator<? super E> comparator)
public TreeSet(Collection<? extends E> c)
public TreeSet(SortedSet s)
TreeSet的一些方法
public int size()
public boolean isEmpty()
public boolean contains(Object o)
public boolean add(E e)
public boolean remove(Object o)
public void clear()
public boolean addAll(Collection<? extends E> c)
Queue接口
PriorityQueue
public class PriorityQueue extends AbstractQueue…
特点:
- 队头存储最大值或最小值(通过堆结构来实现)
- 数据可以重复
- 不能存储null
总结
实现类 | 是否重复 | 数据是否有序 | 是否能存储null | 需要了解 |
---|---|---|---|---|
HashMap | key不重复 | 插入无序 | key,value都可以为null,线程不安全 | 哈希表、散列码、哈希冲突、链地址法、红黑树 |
LinkedHashMap | key不重复 | 插入有序 ,线程安全 | key,value都可以存储null | header、accessOrder |
TreeMap | key不重复 | 数据按key升序或降序 | key,value都可以为null | 红黑树 |
WeakHashMap | 只要进行GC,就会对WeakHashMap进行一次回收 | |||
HashTable | key不重复 | key,value都不能为空,线程安全 | - | 已淘汰 |
实现类 | 特点 | 应用场景 |
---|---|---|
HashSet | 数据无序,不能重复,能存储null | 数据去重 |
LinkedHashSet | 数据有序,不能重复,能存储null | 数据去重、插入有序 |
TreeSet | 数据从小到大或从大到小排序,不能重复,不能存储null | 数据去重、按特定大小排序 |
(不定时补充)