Какие функциональные интерфейсы Map добавляет в Java 8?

Java

Новые методы на карте

По сравнению с Collection у Map больше методов!

forEach()

Сигнатура этого метода void forEach(BiConsumer action), и его функция заключается в выполнении операции, заданной действием, над каждой картой в Map, где BiConsumer — функциональный интерфейс, который имеет реализуемый метод недействителен (T t, U u).

Ни имя интерфейса BinConsumer, ни имя метода accept() не важны, пожалуйста, не запоминайте их.

Требование: Предположим, что существует карта чисел для соответствующих английских слов, выведите все отношения сопоставления на карте. Java7 и предыдущий классический код выглядят следующим образом:

// Java7以及之前迭代Map
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
for(Map.Entry<Integer, String> entry : map.entrySet()){
    System.out.println(entry.getKey() + "=" + entry.getValue());
}

При использовании метода Map.forEach() в сочетании с анонимным внутренним классом код выглядит следующим образом:

// 使用forEach()结合匿名内部类迭代Map
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.forEach(new BiConsumer<Integer, String>(){
    @Override
    public void accept(Integer k, String v){
        System.out.println(k + "=" + v);
    }
});

Приведенный выше код вызывает метод forEach() и реализует интерфейс BiConsumer с помощью анонимного внутреннего класса.

Конечно, никто не использует анонимные внутренние классы в практических сценариях, потому что есть лямбда-выражения:

// 使用forEach()结合Lambda表达式迭代Map
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.forEach((k, v) -> System.out.println(k + "=" + v));
}

getOrDefault()

Этот метод не имеет ничего общего с лямбда-выражениями, но полезен.

Сигнатура метода — V getOrDefault(Object key, V defaultValue), которая используется для запроса соответствующего значения на карте в соответствии с заданным ключом и возврата значения по умолчанию, если оно не найдено.

Используя этот метод, программист может сохранить проблему запроса, существует ли указанное значение ключа.

Требования; предполагая, что существует карта чисел для соответствующих английских слов, выведите английское слово, соответствующее 4, и выведите NoValue, если оно не существует

// 查询Map中指定的值,不存在时使用默认值
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
// Java7以及之前做法
if(map.containsKey(4)){ // 1
    System.out.println(map.get(4));
}else{
    System.out.println("NoValue");
}
// Java8使用Map.getOrDefault()
System.out.println(map.getOrDefault(4, "NoValue")); // 2

putIfAbsent() Этот метод не имеет ничего общего с лямбда-выражениями, но полезен.

Сигнатура метода - V putIfAbsent(K key, V value), функция состоит в том, чтобы поместить значение, указанное значением, в карту только тогда, когда нет сопоставления значения ключа или значение сопоставления равно нулю, в противном случае карта не будет измененный.

Этот метод объединяет условное суждение и присваивание в одно, что более удобно в использовании.

remove()

Все мы знаем, что на карте есть метод удаления (ключ объекта) для удаления отношения сопоставления на карте в соответствии с указанным значением ключа; Java8 добавила метод удаления (ключ объекта, значение объекта), только в текущей карте ключ точно сопоставлен со значением, удалите сопоставление, иначе ничего не делайте.

replace()

В Java7 и более ранних версиях заменить отношение сопоставления на карте можно с помощью метода put(K key, V value), который всегда будет заменять исходное значение новым значением.

Чтобы более точно управлять поведением замены, Java8 добавляет в карту два метода replace(), а именно:

  • replace(ключ K, значение V), используйте значение для замены исходного значения только тогда, когда существует сопоставление ключа в текущей карте, в противном случае ничего не делайте.

  • replace(K key, V oldValue, V newValue), используйте newValue для замены исходного значения только тогда, когда сопоставление ключа в текущей карте существует и равно oldValue, в противном случае ничего не делайте.

replaceAll() Сигнатура этого метода — replaceAll(BiFunction super K,? super V,? extends V> function), которая выполняет операцию, указанную функцией на каждой карте на карте, и заменяет исходное значение на результат выполнения функции , где BiFunction — функциональный интерфейс, который имеет реализуемый метод R apply(T t, U u).

Не пугайтесь такого количества функциональных интерфейсов, потому что вам не нужно знать их названия, чтобы их использовать.

Требование: Предполагая, что существует сопоставление чисел с соответствующими английскими словами, преобразуйте слова в исходном сопоставлении в верхний регистр. Java7 и предыдущий классический код выглядят следующим образом:

// Java7以及之前替换所有Map中所有映射关系
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
for(Map.Entry<Integer, String> entry : map.entrySet()){
    entry.setValue(entry.getValue().toUpperCase());
}

Используйте метод replaceAll() в сочетании с анонимными внутренними классами, чтобы добиться следующего:

// 使用replaceAll()结合匿名内部类实现
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.replaceAll(new BiFunction<Integer, String, String>(){
    @Override
    public String apply(Integer k, String v){
        return v.toUpperCase();
    }
});

Приведенный выше код вызывает метод replaceAll() и использует анонимный внутренний класс для реализации интерфейса BiFunction.

Идем дальше, используя лямбда-выражения для достижения следующего:

// 使用replaceAll()结合Lambda表达式实现
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.replaceAll((k, v) -> v.toUpperCase());

Невероятно лаконично.

merge()

Сигнатура этого метода — слияние (ключ K, значение V, BiFunction super V,? super V,? extends V> remappingFunction), а функция такова:

  • Если карта, соответствующая ключу в Карте, не существует или имеет значение null, свяжите значение (которое не может быть нулевым) с ключом;

  • В противном случае выполняется remappingFunction, если результат выполнения не нулевой, то результат связывается с ключом, в противном случае сопоставление ключа удаляется в Map.

Интерфейс функции BiFunction в параметрах был введен ранее, и существует метод, который необходимо реализовать R apply(T t, U u).

Хотя семантика метода merge() немного сложна, метод очень ясен.Общим сценарием является добавление новой информации об ошибке к исходной информации, например:

map.merge(key, newMsg, (v1, v2) -> v1+v2);

compute()

Сигнатура этого метода — calculate(K key, BiFunction super K,? super V,? extends V> remappingFunction), и функция должна связать результат вычисления remappingFunction с ключом. Если результат вычисления равен нулю, удалить ключ в карте сопоставления.

Чтобы реализовать приведенный выше пример объединения сообщений об ошибках в методе merge(), используйте код calculate() следующим образом:

map.compute(key, (k,v) -> v==null ? newMsg : v.concat(newMsg));

computeIfAbsent()

Сигнатура метода - V calculateIfAbsent(K key, Function super K,? extends V> mappingFunction), функция: только когда нет сопоставления значения ключа в текущей карте или значение сопоставления равно нулю, mapFunction будет вызываться, и в поле Когда результат выполнения mapFunction не равен нулю, свяжите результат с ключом.

Функция — это функциональный интерфейс с реализуемым методом R apply(T t).

calculateIfAbsent() часто используется для создания карты инициализации для определенного значения ключа Map. Например, если мы хотим реализовать карту с несколькими значениями, определение карты может быть Map, Чтобы поместить новые значения в карту, мы можем реализовать следующий код:

Map<Integer, Set<String>> map = new HashMap<>();
// Java7及以前的实现方式
if(map.containsKey(1)){
    map.get(1).add("one");
}else{
    Set<String> valueSet = new HashSet<String>();
    valueSet.add("one");
    map.put(1, valueSet);
}
// Java8的实现方式
map.computeIfAbsent(1, v -> new HashSet<String>()).add("yi");

Используйте calculateIfAbsent(), чтобы объединить условное суждение и операцию сложения, чтобы сделать код более кратким.

computeIfPresent()

Сигнатурой этого метода является V calculateIfPresent(K key, BiFunction super K,? super V,? extends V> remappingFunction), что является противоположностью calculateIfAbsent(), то есть только при наличии сопоставления ключа значение в текущей карте, и оно не равно null , вызовите remappingFunction, если результат remappingFunction равен нулю, удалите сопоставление ключа, в противном случае используйте результат для замены исходного сопоставления ключа.

Функция этой функции эквивалентна следующему коду:

// Java7及以前跟computeIfPresent()等效的代码
if (map.get(key) != null) {
    V oldValue = map.get(key);
    V newValue = remappingFunction.apply(key, oldValue);
    if (newValue != null)
        map.put(key, newValue);
    else
        map.remove(key);
    return newValue;
}
return null;