zoukankan      html  css  js  c++  java
  • 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 就没有实现,前者为可变集合,后者为不可变集合。

  • 相关阅读:
    declare handler 声明异常处理的语法
    mysql存储过程获取sqlstate message_text
    mongoTemplate操作内嵌文档
    mysql索引之七:组合索引中选择合适的索引列顺序
    mongoDB的操作总结
    explain之三:MYSQL EXPLAIN语句的extended 选项学习体会,分析诊断工具之二
    状态模式
    代码重构----使用java有限状态机来消除太多的if else判断
    断路器(CircuitBreaker)设计模式
    断路器之一:Hystrix 使用与分析
  • 原文地址:https://www.cnblogs.com/yangk1996/p/12653368.html
Copyright © 2011-2022 走看看