源码分析三、Map(1)

一、概述

  1. Map是一种数据结构,以键值对的方式存储数据,每个键都是唯一的,且对应一个值,一种存放键值对的集合。
  2. java.util.Map,是一个顶级接口,提供了三个集合视图:所有key的集合、所有value的集合、所有key-value的集合。PS:任何对集合视图的修改都会影响原集合。
  3. Map与Set集合紧密相关,HashSet内部就维护了一个HashMap,实际上HashSet的新增,就是新增了一个key为值,value为默认对象的HashMap元素。

简单介绍一下Set结构特性:

1)无序性:集合中的每个元素都是无序的(java提供SortedSet有序Set)

2)互异性:集合中任意两个元素互异

3)确定性:元素存在与否是确定的

 

二、源码环境

JDK8

三、源码

先介绍java.util.Map接口,jdk8新增了默认方法。

public interface Map<K,V> {
    // 查询Operations

    返回键值对的个数,如果元素个数大于Integer.MAX_VALUE,返回Integer.MAX_VALUE
    int size();

    如果Map没有包含元素,返回true;否则返回,false
    boolean isEmpty();

    是否包含指定key,包含返回true;否则返回,false
    boolean containsKey(Object key);

    是否包含指定value,包含返回true;否则返回,false
    boolean containsValue(Object value);

    根据指定的key,返回对应的value;如果不包含key,返回null
    V get(Object key);

    // 修改Operations

    新增键值对,如果Map中包含key,返回旧的value;否则返回null
    V put(K key, V value);

    删除集合中指定key,如果map不包含指定key,返回null
    V remove(Object key);


    // 批量Operations

    将指定map新增至当前map
    void putAll(Map<? extends K, ? extends V> m);

    清除当前map所有元素
    void clear();


    // 集合视图

    返回所有key的set集合
    Set<K> keySet();

    返回所有value的集合
    Collection<V> values();

    返回所有的键值对的集合
    Set<Map.Entry<K, V>> entrySet();

    内部键值对接口
    interface Entry<K,V> {
        返回key
        K getKey();

        返回value
        V getValue();

        设置新value,返回旧的值
        V setValue(V value);

        判断指定entry和当前entry是否相等
        boolean equals(Object o);

        返回key的hashCode和value的hashCode的按位异或结果
        int hashCode();

        jdk8默认方法,返回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());
        }

        jdk8默认方法,返回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());
        }

        jdk8默认方法,通过指定的key值比较器返回比较器
        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());
        }

        jdk8默认方法,通过指定的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());
        }
    }

    // 比较和hash

    指定map和当前map是否相等
    boolean equals(Object o);

    返回当前map的hash值
    int hashCode();

    // 默认方法

    JDK8默认方法,获取key查找value,如果key不存在或者value为null返回指定的默认值
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

    jdk8默认方法,用于Lambda表达式,遍历map,通过action处理
    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);
        }
    }

    JDK8默认方法,用于Lambda表达式,提供BiFunction用来根据旧的k-v键值对,生成新的value,并更新当前map
    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);
            }
        }
    }

    JDK8默认方法,新增键值对,如果当前key已存在且value不为null,返回对应的value;否则新增key-value,返回null
    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

    JDK8默认方法,指定key对应的value和指定的value相等,才会删除key,返回true;否则,返回false
    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;
    }

    JDK8默认方法,仅当当前key存在且对应的value不为空且和指定的旧值相等,put新值
    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;
    }

    JDK8默认方法,仅当当前key存在或对应的value不为空,put新值
    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

    JDK8默认方法,当key不存在或者对应的value为null时,使用指定的行为,传入一个参数,返回一个结果值,
返回结果值不为null,put新值,返回添加的新值,否则返回不为空的旧值
    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;
    }

    JDK8默认方法,与computeIfAbsent类似,不过该方法需要指定的行为参数,key和旧值,返回新值
    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;
        }
    }

    JDK8默认方法,提供两个参数的行为函数,用于生成新值,如果新值为空,旧值不为空或包含key,删除key;
如果新值不为空,put进map,返回新值;
    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;
        }
    }

    JDK8默认方法,提供key,value(想更新的值)以及两个参数的行为函数,如果旧值weinull,新值直接使用提供的value,
否则,通过行为函数,传入旧值和指定的value来生成对应的新值;
如果新值为null,删除原map的key;否则,put新值到map中
    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;
    }
}

猜你喜欢

转载自blog.csdn.net/stubborn_ugly/article/details/83028440
今日推荐