java集合类——Map

总关系图

在这里插入图片描述

接口

Map

public interface Map<K,V> {
    // Query Operations
    // 返回map的大小
    int size();
    // 判断map是否为空
    boolean isEmpty();
    // 判断map中是否含有key
    boolean containsKey(Object key);
    // 判断map中是否含有这个value
    boolean containsValue(Object value);
    // 根据 key 得到 value
    V get(Object key);
    // Modification Operations
    // 设置 key 对应的 value值
    V put(K key, V value);
    // 移除这个key
    V remove(Object key);
    // Bulk Operations
    // 将新map 添加进该map
    void putAll(Map<? extends K, ? extends V> m);
    // 清除
    void clear();
    // Views
    // 得到key的集合
    Set<K> keySet();
    // 得到values的集合
    Collection<V> values();
    // 得到 key,value的集合
    Set<Map.Entry<K, V>> entrySet();
    // 内部接口,每个key对应着一个value,称这么一条一个entry
    interface Entry<K,V> {
        // 得到entry中的key
        K getKey();
        // 得到entry中的value
        V getValue();
        // 设置value
        V setValue(V value);
        // 比较 Object o
        boolean equals(Object o);
        // 得到hashcode
        int hashCode();
        // 比较key值
        public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> c1.getKey().compareTo(c2.getKey());
        }
        // 比较value值
        public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> c1.getValue().compareTo(c2.getValue());
        }
        // 传入比较器
        public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
        }
        // 传入比较器比较value
        public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
        }
    }
    // Comparison and hashing
    // 比较o对象
    boolean equals(Object o);
    // hashcode
    int hashCode();
    // Defaultable methods
    // java1.8 得到默认值
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }
    // forEach lambda 表达式
    default void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k, v);
        }
    }
    // 通过方法设置新值
    default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        Objects.requireNonNull(function);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }

            // ise thrown from function is not a cme.
            v = function.apply(k, v);

            try {
                entry.setValue(v);
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
        }
    }
    // 如果是null就设置新值,不是null就返回值
    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }
        return v;
    }
    // 移除key对应的value的这个entry
    default boolean remove(Object key, Object value) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, value) ||
            (curValue == null && !containsKey(key))) {
            return false;
        }
        remove(key);
        return true;
    }
    // 替换成新值
    default boolean replace(K key, V oldValue, V newValue) {
        Object curValue = get(key);
        if (!Objects.equals(curValue, oldValue) ||
            (curValue == null && !containsKey(key))) {
            return false;
        }
        put(key, newValue);
        return true;
    }
    // 替换key的value,不需要旧值
    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }
    // 如果key对应的value是null值,则设置新值,如果不是null值则返回原有值
    default V computeIfAbsent(K key,
            Function<? super K, ? extends V> mappingFunction) {
        Objects.requireNonNull(mappingFunction);
        V v;
        if ((v = get(key)) == null) {
            V newValue;
            if ((newValue = mappingFunction.apply(key)) != null) {
                put(key, newValue);
                return newValue;
            }
        }
        return v;
    }
    // 如果有则设置新值,如果没有则返回null
    default V computeIfPresent(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        V oldValue;
        if ((oldValue = get(key)) != null) {
            V newValue = remappingFunction.apply(key, oldValue);
            if (newValue != null) {
                put(key, newValue);
                return newValue;
            } else {
                remove(key);
                return null;
            }
        } else {
            return null;
        }
    }
    // 新值是null的话,旧值不是null,则移除key
    // 如果新值不为null,则设置新值
    default V compute(K key,
            BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        V oldValue = get(key);

        V newValue = remappingFunction.apply(key, oldValue);
        if (newValue == null) {
            // delete mapping
            if (oldValue != null || containsKey(key)) {
                // something to remove
                remove(key);
                return null;
            } else {
                // nothing to do. Leave things as they were.
                return null;
            }
        } else {
            // add or replace old mapping
            put(key, newValue);
            return newValue;
        }
    }
    // map.merge(key, msg, String::concat)
    // 将新值和旧值传入方法内,返回操作后的新值,作为key的value
    default V merge(K key, V value,
            BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);
        V oldValue = get(key);
        V newValue = (oldValue == null) ? value :
                   remappingFunction.apply(oldValue, value);
        if(newValue == null) {
            remove(key);
        } else {
            put(key, newValue);
        }
        return newValue;
    }
}

SortedMap

SortedMap 继承 Map

public interface SortedMap<K,V> extends Map<K,V> {
    // 得到比较器
    Comparator<? super K> comparator();
    // 返回从from到to的部分视图
    SortedMap<K,V> subMap(K fromKey, K toKey);
    // 返回小于key的部分视图
    SortedMap<K,V> headMap(K toKey);
    // 返回大于等于这个key的部分视图
    SortedMap<K,V> tailMap(K fromKey);
    // 得到第一个key
    K firstKey();
    // 得到最后一个key
    K lastKey();
    // 得到key的集合
    Set<K> keySet();
    // 得到value的集合
    Collection<V> values();
    // 得到entry的集合
    Set<Map.Entry<K, V>> entrySet();
}

NavigableMap

继承自 SortedMap

public interface NavigableMap<K,V> extends SortedMap<K,V> {
    // 严格小于key的最大值的entry
    Map.Entry<K,V> lowerEntry(K key);
    // 严格小于key的最大值
    K lowerKey(K key);
    // 小于等于key值的最大key的entry
    Map.Entry<K,V> floorEntry(K key);
    // 小于等于key值的最大key
    K floorKey(K key);
    // 大于等于key值的最小值的entry
    Map.Entry<K,V> ceilingEntry(K key);
    // 大于等于key值的最小值
    K ceilingKey(K key);
    // 比key大的最小值的entry
    Map.Entry<K,V> higherEntry(K key);
    // 比key大的最小值
    K higherKey(K key);
    // 第一个entry
    Map.Entry<K,V> firstEntry();
    // 得到最后一个entry
    Map.Entry<K,V> lastEntry();
    // 删除并返回第一个entry
    Map.Entry<K,V> pollFirstEntry();
    // 删除并返回最后一个entry
    Map.Entry<K,V> pollLastEntry();
    // 返回降序的map
    NavigableMap<K,V> descendingMap();
    // 返回key集合
    NavigableSet<K> navigableKeySet();
    // 返回 降序的 key集合
    NavigableSet<K> descendingKeySet();
    // 如果true 就包含
    NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
                             K toKey,   boolean toInclusive);
    // 如果 inclusive 为 true 返回的视图里面就包含 tokey
    NavigableMap<K,V> headMap(K toKey, boolean inclusive);
    // 如果 inclusive 为 true 返回的视图里面就包含 fromkey
    NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
}

抽象类

AbstractMap

一些默认方法的实现,可以被覆盖

具体类

HashMap

默认值

// 默认初始容器大小
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
// 最大容量值
static final int MAXIMUM_CAPACITY = 1 << 30;
// 阈值为容量的3/4
static final float DEFAULT_LOAD_FACTOR = 0.75f;
// 
static final int TREEIFY_THRESHOLD = 8;
//
static final int UNTREEIFY_THRESHOLD = 6;
//
static final int MIN_TREEIFY_CAPACITY = 64;

hash值的取法

static final int hash(Object key) {
    int h;
    // h显示被key的hashCode赋值,再h右移16位做异或操作。
    // 高16位与低16位做异或运算,防止在数组太小的时候,hash冲突严重
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

重新计算大小

final Node<K,V>[] resize() {
    Node<K,V>[] oldTab = table;
    // 老的容量
    int oldCap = (oldTab == null) ? 0 : oldTab.length;
    // 老的阈值 (容量*负载因子)
    int oldThr = threshold;
    int newCap, newThr = 0;
    // 如果old容量>0
    if (oldCap > 0) {
    	// 如果old容量大于 最大容量
        if (oldCap >= MAXIMUM_CAPACITY) {
        	// 阈值为int最大值
            threshold = Integer.MAX_VALUE;
            // 返回old map数组
            return oldTab;
        }
        // 如果不大于max,new容量 = old容量*2 小于最大容量 且 old容量 >= 16
        else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                 oldCap >= DEFAULT_INITIAL_CAPACITY)
            // new阈值 = old阈值*2
            newThr = oldThr << 1; // double threshold
    }
    // 如果old阈值>0
    else if (oldThr > 0) // initial capacity was placed in threshold
        newCap = oldThr;
    // 其余的情况,初始化的时候    
    else {               // zero initial threshold signifies using defaults
    	// new容量 = 16
        newCap = DEFAULT_INITIAL_CAPACITY;
        // new阈值 = 12
        newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
    }
    // 如果新的阈值 = 0
    if (newThr == 0) {
    	// 如果容量或者阈值过大,直接设置阈值为最大值
        float ft = (float)newCap * loadFactor;
        newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
                  (int)ft : Integer.MAX_VALUE);
    }
    // 全局阈值 = new阈值
    threshold = newThr;
    @SuppressWarnings({"rawtypes","unchecked"})
    // 创建新容量的map数组,赋值给table
        Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];    
    table = newTab;
    if (oldTab != null) {
    	// 遍历old容器
        for (int j = 0; j < oldCap; ++j) {
            Node<K,V> e;
            if ((e = oldTab[j]) != null) {
                oldTab[j] = null;
                // 当前位置没有冲突的情况下
                if (e.next == null)
                	// 放置到新的位置
                    newTab[e.hash & (newCap - 1)] = e;
                else if (e instanceof TreeNode)
                	// 进行分割,太长则进行树化
                    ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                else { // 保持顺序
                    Node<K,V> loHead = null, loTail = null;
                    Node<K,V> hiHead = null, hiTail = null;
                    Node<K,V> next;
                    do {
                        next = e.next;
                        if ((e.hash & oldCap) == 0) {
                            if (loTail == null)
                                loHead = e;
                            else
                                loTail.next = e;
                            loTail = e;
                        }
                        else {
                            if (hiTail == null)
                                hiHead = e;
                            else
                                hiTail.next = e;
                            hiTail = e;
                        }
                    } while ((e = next) != null);
                    if (loTail != null) {
                        loTail.next = null;
                        newTab[j] = loHead;
                    }
                    if (hiTail != null) {
                        hiTail.next = null;
                        newTab[j + oldCap] = hiHead;
                    }
                }
            }
        }
    }
    return newTab;
}
// 只有在resize里面才调用 split方法
final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
    TreeNode<K,V> b = this;
    // Relink into lo and hi lists, preserving order
    TreeNode<K,V> loHead = null, loTail = null;
    TreeNode<K,V> hiHead = null, hiTail = null;
    int lc = 0, hc = 0;
    // hash&bit = 0的为一个链表,不为0的为一个链表
    for (TreeNode<K,V> e = b, next; e != null; e = next) {
        next = (TreeNode<K,V>)e.next;
        e.next = null;
        // lc 和 hc 计数长度
        if ((e.hash & bit) == 0) {
            if ((e.prev = loTail) == null)
                loHead = e;
            else
                loTail.next = e;
            loTail = e;
            ++lc;
        }
        else {
            if ((e.prev = hiTail) == null)
                hiHead = e;
            else
                hiTail.next = e;
            hiTail = e;
            ++hc;
        }
    }
    if (loHead != null) {
    	// 小于 6 不进行树化
        if (lc <= UNTREEIFY_THRESHOLD)
            tab[index] = loHead.untreeify(map);
        else {
            tab[index] = loHead;
            if (hiHead != null) // (else is already treeified)
                loHead.treeify(tab);
        }
    }
    if (hiHead != null) {
        if (hc <= UNTREEIFY_THRESHOLD)
            tab[index + bit] = hiHead.untreeify(map);
        else {
            tab[index + bit] = hiHead;
            if (loHead != null)
                hiHead.treeify(tab);
        }
    }
}

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
// onlyIfAbsent 若为true则不改变现有值
// evict 如果是false,则table还是处于创建模式
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    // 如果table是空的,则
    if ((tab = table) == null || (n = tab.length) == 0)
    	// 返回新的长度
        n = (tab = resize()).length;
    // 位置是空的则进行插入    
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    // 不为空,则里面可能是链表,可能是红黑树    
    else {
    	
        Node<K,V> e; K k;
        // 检查第一个
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
		// 如果是红黑树节点,先查询如果没有则插入新节点(调节平衡),有则返回            
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
        	// 对链表循环,深度如果大于等于 7 就进行树化
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                // 找到,break
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        // 如果e不等于null,说明key是存在的
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    // 操作数++
    ++modCount;
    // 如果size大于阈值,进行resize
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}

public V remove(Object key) {
    Node<K,V> e;
    return (e = removeNode(hash(key), key, null, false, true)) == null ?
        null : e.value;
}

final Node<K,V> removeNode(int hash, Object key, Object value,
                           boolean matchValue, boolean movable) {
    Node<K,V>[] tab; Node<K,V> p; int n, index;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (p = tab[index = (n - 1) & hash]) != null) {
        Node<K,V> node = null, e; K k; V v;
        // 先判断第一个
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            node = p;    
        else if ((e = p.next) != null) {
        	// 如果是红黑树的节点,则得到节点
            if (p instanceof TreeNode)
                node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
            else {
            // 如果是链表的
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key ||
                         (key != null && key.equals(k)))) {
                        node = e;
                        break;
                    }
                    p = e;
                } while ((e = e.next) != null);
            }
        }
        if (node != null && (!matchValue || (v = node.value) == value ||
                             (value != null && value.equals(v)))) {
   			// 如果是红黑树,则移除节点                          
            if (node instanceof TreeNode)
                ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
            // 链表就等于该节点的next    
            else if (node == p)
                tab[index] = node.next;
            else
            	// 不是链表头,就等于next
                p.next = node.next;
            // 操作数++    
            ++modCount;
            // 大小--
            --size;
            afterNodeRemoval(node);
            return node;
        }
    }
    return null;
}

// java 1.8
public V get(Object key) {
    Node<K,V> e;
    // 先得到key的hash值,再根据hash值和key对象去获取值
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    // table为现有的map数组,且数组的长度大于0,且(n - 1) & hash的值不为null
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        // 判断第一个的key是否与传入的相等
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k))))
            return first;
        // 如果第一个不是,则判断下一个
        if ((e = first.next) != null) {
        	// 如果是红黑树节点
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
            // 链表
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

HashTable

HashTable 与 hashMap 类似,只是他的每个方法都是 synchronized修饰的,每个操作都需要同步,所以效率很差

WeakHashMap

里面的entry是weak引用。所以只要发生gc,没有被引用的对象肯定会被回收。
这里复习下4种引用

  1. 强引用,引用被GCRoots 链上的变量引用着
  2. 软引用,发生gc时不会被回收,只有在要发生OOM的前夕,才会被回收,具体的话Hotspot里面是计算空间只剩下10MB的时候会对软引用进行回收。
  3. 弱引用:只要发生gc就会被回收
  4. 虚引用:无法获取对象,只有在对象被回收的时候,会收到一个系统通知。

TreeMap

内部由红黑树存储,插入、删除都要符合红黑数的规则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值