jdk8这样使用Map

作者: zheng93775 | 来源:发表于2019-06-22 15:42 被阅读3次

jdk8中接口增加了default方法,可以在接口里实现简单的公共逻辑。本篇文章介绍一下java.util.Map里新出的default方法,平常写代码的时候很可能能用上,可以帮助我们写出更优雅的代码。

getOrDefault

获取key对应的value,当key不存在时,返回默认值

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

// 测试
@Test
public void getOrDefault() {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 3);
    Integer resultB = map.getOrDefault("B", 0);
    System.out.println("resultB: " + resultB);
    Integer resultD = map.getOrDefault("D", 0);
    System.out.println("resultD: " + resultD);
}

/* 测试结果
resultB: 2
resultD: 0
*/

forEach

遍历

// 源码
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);
    }
}

// 测试
@Test
public void forEach() {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 3);
    
    // 我们以前使用Entry遍历
    for (Map.Entry<String, Integer> entry : map.entrySet()) {
        System.out.println(entry.getKey() + " -> " + entry.getValue());
    }
    
    // 现在forEach简单很多
    map.forEach((key, value) -> {
        System.out.println(key + " -> " + value);
    });
}

replaceAll

按照指定的逻辑替换所有value

// 源码
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);
        }
    }
}

// 测试
@Test
public void replaceAll() {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 3);
    map.replaceAll((key, value) -> value + 10);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
A -> 11
B -> 12
C -> 13
*/

putIfAbsent

缺少值时填充

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

// 测试
@Test
public void putIfAbsent() {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", null);
    map.putIfAbsent("A", 11);
    map.putIfAbsent("B", 12);
    map.putIfAbsent("C", 13);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
A -> 1
B -> 12
C -> 13
*/

remove

键值对匹配时移除

// 源码
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;
}

// 测试
@Test
public void remove() {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 2);
    map.put("C", 3);
    map.remove("A", 1);
    map.remove("B", 1);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
B -> 2
C -> 3
*/

replace

存在或者匹配时进行替换

// 源码
default V replace(K key, V value) {
    V curValue;
    if (((curValue = get(key)) != null) || containsKey(key)) {
        curValue = put(key, value);
    }
    return curValue;
}
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;
}

// 测试
@Test
public void replace() {
    Map<String, Integer> map = new HashMap<>();
    map.put("A", 1);
    map.put("B", 1);
    System.out.println("=== replace(K key, V value) ===");
    map.replace("B", 2);
    map.replace("C", 3);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));

    System.out.println("=== replace(K key, V oldValue, V newValue) ===");
    map.replace("A", 2, 11);
    map.replace("B", 2, 12);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
=== replace(K key, V value) ===
A -> 1
B -> 2
=== replace(K key, V oldValue, V newValue) ===
A -> 1
B -> 12
*/

computeIfAbsent

缺少值时写入计算结果

// 源码
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;
}

// 测试
@Test
public void computeIfAbsent() {
    Map<Character, Integer> map = new HashMap<>();
    map.put('A', 65);
    map.put('B', 66);
    map.put('C', null);
    map.computeIfAbsent('C', (key) -> (int) key);
    map.computeIfAbsent('D', (key) -> (int) key);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
A -> 65
B -> 66
C -> 67
D -> 68
*/

computeIfPresent

存在时进行计算,使用计算值进行替换(计算值为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;
    }
}

// 测试
@Test
public void computeIfPresent() {
    Map<Character, Integer> map = new HashMap<>();
    map.put('A', 1);
    map.put('B', 2);
    map.put('C', null);
    map.computeIfPresent('A', (key, oldValue) -> oldValue + 10);
    map.computeIfPresent('B', (key, oldValue) -> null);
    map.computeIfPresent('C', (key, oldValue) -> oldValue + 10);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
A -> 11
C -> null
*/

compute

对指定key进行计算,添加计算值为value(计算值为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;
    }
}

// 测试
@Test
public void compute() {
    Map<Character, Integer> map = new HashMap<>();
    map.put('A', 1);
    map.put('B', 2);
    map.compute('A', (key, oldValue) -> (int) key);
    map.compute('B', (key, oldValue) -> null);
    map.compute('C', (key, oldValue) -> (int) key);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
A -> 65
C -> 67
*/

merge

合并旧值和新值

// 源码
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;
}

// 测试
@Test
public void merge() {
    Map<Character, Integer> map = new HashMap<>();
    map.put('A', 10);
    map.put('B', 10);
    map.merge('A', 1, (oldValue, value) -> oldValue + value);
    map.merge('B', 2, (oldValue, value) -> oldValue + value);
    map.merge('C', 3, (oldValue, value) -> oldValue + value);
    map.forEach((key, value) -> System.out.println(key + " -> " + value));
}

/* 测试结果
A -> 11
B -> 12
C -> 3
*/

相关文章

网友评论

    本文标题:jdk8这样使用Map

    本文链接:https://www.haomeiwen.com/subject/swomqctx.html