目录
Map
SortedMap
Dictionary
一、HashMap
1.构造函数
2.数据结构
3.API
4.源码
5.遍历
二、Hashtable
三、TreeMap
1.构造方法
2.数据结构
3.API
4.遍历
四、LinkedHashMap
1.构造函数
2.数据结构
3.遍历:
public interface Map
abstract void clear()
abstract boolean containsKey(Object key)
abstract boolean containsValue(Object value)
abstract Set> entrySet()
abstract boolean equals(Object object)
abstract V get(Object key)
abstract int hashCode()
abstract boolean isEmpty()
abstract Set keySet()
abstract V put(K key, V value)
abstract void putAll(Map extends K, ? extends V> map)
abstract V remove(Object key)
abstract int size()
abstract Collection values()
Map提供接口分别用于返回 键集、值集或键-值映射关系集。
Map提供了“键-值对”、“根据键获取值”、“删除键”、“获取容量大小”等方法。
Map.Entry是Map中内部的一个接口,Map.Entry是键值对,Map通过 entrySet() 获取Map.Entry的键值对集合,从而通过该集合实现对键值对的操作
public interface SortedMap
SortedMap是一个继承于Map接口的接口。它是一个有序的SortedMap键值映射。
SortedMap的排序方式有两种:自然排序 或者 用户指定比较器。 插入有序 SortedMap 的所有元素都必须实现 Comparable 接口(或者被指定的比较器所接受)。
所有SortedMap 实现类都应该提供 4 个“标准”构造方法:
API
// SortedMap新增的API
abstract Comparator super K> comparator()
abstract K firstKey()
abstract SortedMap headMap(K endKey)
abstract K lastKey()
abstract SortedMap subMap(K startKey, K endKey)
abstract SortedMap tailMap(K startKey)
public interface NavigableMapextends SortedMap { }
NavigableMap是继承于SortedMap的接口。它是一个可导航的键-值对集合,具有了为给定搜索目标报告最接近匹配项的导航方法。
NavigableMap分别提供了获取“键”、“键-值对”、“键集”、“键-值对集”的相关方法。
public abstract class Dictionary{}
NavigableMap是JDK 1.0定义的键值对的接口,它也包括了操作键值对的基本函数。
// 默认构造函数。
HashMap()
// 指定“容量大小”的构造函数
HashMap(int capacity)
// 指定“容量大小”和“加载因子”的构造函数
HashMap(int capacity, float loadFactor)
// 包含“子Map”的构造函数
HashMap(Map extends K, ? extends V> map)
// 默认的初始容量是16,必须是2的幂。
static final int DEFAULT_INITIAL_CAPACITY = 16;
// 最大容量(必须是2的幂且小于2的30次方,传入容量过大将被这个值替换)
static final int MAXIMUM_CAPACITY = 1 << 30;
// 默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
// 存储数据的Entry数组,长度是2的幂。
// HashMap是采用拉链法实现的,每一个Entry本质上是一个单向链表
transient Entry[] table;
// HashMap的大小,它是HashMap保存的键值对的数量
transient int size;
// HashMap的阈值,用于判断是否需要调整HashMap的容量(threshold = 容量*加载因子)
int threshold;
// 加载因子实际大小
final float loadFactor;
// HashMap被改变的次数
transient volatile int modCount;
HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。
容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。
加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子是 0.75, 这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。
默认初始容量是16
HashMap继承于AbstractMap类,实现了Map接口。Map是"key-value键值对"接口,AbstractMap实现了"键值对"的通用函数接口。
HashMap是通过"拉链法"实现的哈希表。它包括几个重要的成员变量:table, size, threshold, loadFactor, modCount。
Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 数组+链表+红黑 树 组成。
根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的 具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决 于链表的长度,为 O(n)。为了降低这部分的开销,在 Java8 中,当链表中的元素超过了 8 个以后, 会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)。
void clear()
Object clone()
boolean containsKey(Object key)
boolean containsValue(Object value)
Set> entrySet()
V get(Object key)
boolean isEmpty()
Set keySet()
V put(K key, V value)
void putAll(Map extends K, ? extends V> map)
V remove(Object key)
int size()
Collection values()
https://blog.csdn.net/M_azed/article/details/91044139
第一步:根据entrySet()获取HashMap的“键值对”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
// 获取key
key = (String)entry.getKey();
// 获取value
integ = (Integer)entry.getValue();
}
第一步:根据keySet()获取HashMap的“键”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
// 获取key
key = (String)iter.next();
// 根据key,获取value
integ = (Integer)map.get(key);
}
第一步:根据value()获取HashMap的“值”的集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是HashMap对象
// map中的key是String类型,value是Integer类型
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
TreeMap是通过红黑树实现的,TreeMap存储的是key-value键值对,TreeMap的排序是基于对key的排序。
TreeMap提供了操作“key”、“key-value”、“value”等方法,也提供了对TreeMap这颗树进行整体操作的方法,如获取子树、反向树。
// 默认构造函数。使用该构造函数,TreeMap中的元素按照自然排序进行排列。
TreeMap()
// 创建的TreeMap包含Map
TreeMap(Map extends K, ? extends V> copyFrom)
// 指定Tree的比较器
TreeMap(Comparator super K> comparator)
// 创建的TreeSet包含copyFrom
TreeMap(SortedMap copyFrom)
//root为实际存储
private transient Entry root = null;
private transient int size = 0;
private static final boolean RED = false;
private static final boolean BLACK = true;
private final Comparator super K> comparator;
static final class Entry implements Map.Entry {
K key;
V value;
Entry left = null;
Entry right = null;
Entry parent;
boolean color = BLACK;
}
TreeMap的本质是R-B Tree(红黑树),它包含几个重要的成员变量: root, size, comparator
Entry ceilingEntry(K key)
K ceilingKey(K key)
void clear()
Object clone()
Comparator super K> comparator()
boolean containsKey(Object key)
NavigableSet descendingKeySet()
NavigableMap descendingMap()
Set> entrySet()
Entry firstEntry()
K firstKey()
Entry floorEntry(K key)
K floorKey(K key)
V get(Object key)
NavigableMap headMap(K to, boolean inclusive)
SortedMap headMap(K toExclusive)
Entry higherEntry(K key)
K higherKey(K key)
boolean isEmpty()
Set keySet()
Entry lastEntry()
K lastKey()
Entry lowerEntry(K key)
K lowerKey(K key)
NavigableSet navigableKeySet()
Entry pollFirstEntry()
Entry pollLastEntry()
V put(K key, V value)
V remove(Object key)
int size()
SortedMap subMap(K fromInclusive, K toExclusive)
NavigableMap subMap(K from, boolean fromInclusive, K to, boolean toInclusive)
NavigableMap tailMap(K from, boolean inclusive)
SortedMap tailMap(K fromInclusive)
第一步:根据entrySet()获取TreeMap的“键值对”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是TreeMap对象
// map中的key是String类型,value是Integer类型
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
// 获取key
key = (String)entry.getKey();
// 获取value
integ = (Integer)entry.getValue();
}
第一步:根据keySet()获取TreeMap的“键”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是TreeMap对象
// map中的key是String类型,value是Integer类型
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
// 获取key
key = (String)iter.next();
// 根据key,获取value
integ = (Integer)map.get(key);
}
第一步:根据value()获取TreeMap的“值”的集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。
// 假设map是TreeMap对象
// map中的key是String类型,value是Integer类型
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
LinkedHashMap 是 HashMap 的一个子类,保存了记录的插入顺序,在用 Iterator 遍历 LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序
LinkedHashMap可以认为是HashMap+LinkedList,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序
public class LinkedHashMap
extends HashMap
implements Map
{
public LinkedHashMap() {
super();
accessOrder = false;
}
public LinkedHashMap(int initialCapacity) {
super(initialCapacity);
accessOrder = false;
}
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
/**有点特殊的就是这个,多了一个参数accessOrder。存储顺序,LinkedHashMap关键的参数之一就在这个,
*true:指定迭代的顺序是按照访问顺序(近期访问最少到近期访问最多的元素)来迭代的。 false:指定迭代 *的顺序是按照插入顺序迭代,也就是通过插入元素的顺序来迭代所有元素
*如果你想指定访问顺序,那么就只能使用该构造方法,其他三个构造方法默认使用插入顺序。
*/
public LinkedHashMap(int initialCapacity,
float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
public LinkedHashMap(Map extends K, ? extends V> m) { //
super();
accessOrder = false;
putMapEntries(m, false);
}
}
final boolean accessOrder;
transient LinkedHashMap.Entry head;
transient LinkedHashMap.Entry tail;
static class Entry extends HashMap.Node {
Entry before, after;
Entry(int hash, K key, V value, Node next) {
super(hash, key, value, next);
}
}
LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构。该结构由数组和链表或红黑树组成
LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
entrySet() keySet() values() 三种方式
参考文章:
https://www.cnblogs.com/skywang12345/p/3310835.html
https://www.cnblogs.com/skywang12345/p/3310928.html
https://www.imooc.com/article/22931