Map、AbstractMap


Map是一个有键值映射的,但不包括相同key,每个key至多对应一个value。
这个接口替代了Dictionary这个类,Dictionary是抽象类而非接口.
除了一些基本的方法。只要看一下JDK1.8新增的方法

getOrDefault(Object key, V defaultValue)

  default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

返回指定键映射到的值,如果此映射不包含键的映射,则返回 defaultValue 。

 public static void main(String[] args) {
        Map<String,String> m=new HashMap<String,String>(3);
        m.put("1","1");
        m.put("2","2");
        m.put("3","3");
        String orDefault = m.getOrDefault("4", "4");
        System.out.println(orDefault);
    }

forEach(BiConsumer<? super K, ? super V> 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);
        }
    }
 m.forEach((k,v)->System.out.println(k+"-"+v));

replaceAll(BiFunction<? super K, ? super V, ? extends V> function)

    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);
            }
        }
    }

对于map中每一个entry,将其value替换成BiFunction接口返回的值.直到所有entry替换完or出现异常为止.如果执行过程中出现异常,则抛给调用者

  m.replaceAll((k,v)->{
            if(k.equals("4")) {
                v="";
            }
            return v;
        });
        m.forEach((k,v)->System.out.println(k+"-"+v)); 

putIfAbsent(K key, V value)

    default V putIfAbsent(K key, V value) {
        V v = get(key);
        if (v == null) {
            v = put(key, value);
        }

        return v;
    }

如果指定的键尚未与某个值相关联(或映射到 null ), null其与给定值相关联并返回 null ,否则返回当前值。

remove(Object key, Object value)

  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;
    }

如果给定的参数key和value在map中是一个entry,则删除这个entry

replace(K key, V oldValue, V newValue)

    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在map中有entry,则为指定key的entry,用新value替换旧的value.

replace(K key, V value)

    default V replace(K key, V value) {
        V curValue;
        if (((curValue = get(key)) != null) || containsKey(key)) {
            curValue = put(key, value);
        }
        return curValue;
    }

如果指定key在map中有value,则用参数value进行替换

computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction)

  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;
    }

若lambda式返回值!=null,且Key不存在,则在map中新增该组(K,V);且若Key存在,且原value!=null,则不做操作;但原value=null,则更新value值;

        m.computeIfAbsent("5", v -> "5");
        m.forEach((k, v) -> System.out.println(k + "-" + v));

computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

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;
        }
    }

对指定的在map中已经存在的key的value进行操作。只对已经存在key的进行操作,其他不操作。

 m.computeIfPresent("1", (k,v) -> "5");
        m.computeIfPresent("7", (k,v) -> "7");
        m.forEach((k, v) -> System.out.println(k + "-" + v));

注意jdk8中不要尝试对ConcurrentHashMapz类中的computeIfAbsent方法使用递归,会导致一个bug,产生死循环https://mp.weixin.qq.com/s/O6UmB7YDKIYtNvqCOjNwDQ

compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

   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;
        }
    }

计算K,V之间映射关系,根据重映射函数返回新的V值,若返回null,直接删除该组映射.(如果最初不存在则保持不存在)。 如果重映射函数本身引发(未检查)异常,则重新引导异常,并且当前映射保持不变。BiFunction接口的apply的入参为key、oldValue

        m.compute("1", (k,v)->k.length()==v.length()?null:v);
       // m.compute("1", (k,v)->k.length()!=v.length()?null:"33");
        m.forEach((k, v) -> System.out.println(k + "-" + v));

merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)

    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;
    }

如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。 否则,将关联值替换为给定重映射函数的结果,如果结果为null ,则将其null 。如果重映射函数返回null ,则映射将被删除。 如果重映射函数本身引发(未检查)异常,则重新引导异常,并且当前映射保持不变。

  m.merge("1", "in", (k,v)->k+v.toUpperCase());
        m.merge("2", "in", (k,v)->null);
        m.merge("3", "on", (k,v)->"ff");
        m.forEach((k, v) -> System.out.println(k + "-" + v));

AbstractMap

AbstractMap类和AbstractList类一样,都是一种模板类,提供了Map的基本实现。开发人员如果想实现自己的Map,只需要继承AbstractMap类,实现特定方法即可。

我们要实现一个不可变的 Map 时,只需要继承 AbstractMap 类并实现 entrySet() 即可。

如果想要实现一个可变的 Map ,我们还需要重写 put() 方法,因为 AbstractMap 类中默认不支持 put实现,子类必须重写该方法的实现,否则会抛出异常:

public V put(K key, V value) {
    throw new UnsupportedOperationException();
}

Set<Map.Entry<K,V>> entrySet();

 public abstract Set<Map.Entry<K,V>> entrySet();

也就是说所有的子类都必须实现entrySet()方法。纵观AbstractMap中的成员方法内部实现,基本都依赖于entrySet()方法,它返回了Map所保存的键值对。Map集合没有Iterator,如果要去除元素,必须将Map集合转换成Set集合依赖也是entrySet()。

两个成员变量

 //Map中所有的键
 transient Set<K> keySet;
 //Map所有的值
 transient Collection<V> values;
//都是不可序列化的

Set keySet();、Collection values()

这个两个方法没有采用遍历Entry的方式,而是重写了iterator,再调用Entry集合的迭代器。

SimpleEntry、SimpleImmutableEntry两个子类

唯一区别setValue 这个方法。SimpleEntry 支持 setValue 的操作实现,而SimpleImmutableEntry 就没有实现,前者为可变集合,后者为不可变集合。

posted @ 2020-04-07 14:46  无话可说丶  阅读(146)  评论(0编辑  收藏  举报