Передача пользовательского метода для поведения слияния в HashMap Java8 - PullRequest
2 голосов
/ 22 мая 2019

Я хочу предоставить пользовательский метод для слияния карты в Java 8? Созданный вами метод должен принимать две карты и поведение «слияния».

 public <T> Map<? super T, ? super T> mergeMaps( Map<? super T, ? super 
 T> map1, Map<? super T, ? super T> map2 ) {
 // merging code here
 }

но я хочу что-то вроде этого

public <T> Map<? super T, ? super T> mergeMaps( Map<? super T, ? super T> 
map1, Map<? super T, ? super T> map2 , MergeTwoMaps<T, U> mergeTwoMaps) 
{
    // merging code here
}

Как то так. универсальное объединение Java

 Map<String, Integer> map1 = new HashMap<>();
 Map<String, Integer> map2 = new HashMap<>();
 map1.put(“key1”, 20);
 map1.put(“key2”, 30);
 map2.put(“key3”, 40);
 map2.put(“key1”, 50);

mergeMaps(map1,map2,mergeBehaviour)
Output should be
map.get("key1")--> 70

Map<String, String> map1 = new HashMap<>();
 Map<String, String> map2 = new HashMap<>();
 map1.put(“key1”, "Hello");
 map1.put(“key2”, "Hi");
 map2.put(“key3”, "Ok");
 map2.put(“key1”, "world");
 mergeMaps(map1,map2,mergeBehaviour)

 Output should be
 map.get("key1")--> Helloworld

Ответы [ 2 ]

5 голосов
/ 22 мая 2019

Вы должны переосмыслить желаемую подпись метода.Цитировать рекомендации :

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

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

Метод должен выглядеть примерно так:

public static <K, V> Map<K, V> mergeMaps(
    Map<? extends K, ? extends V> map1, Map<? extends K, ? extends V> map2,
    BinaryOperator<V> mergeFunction) {

    Map<K, V> result = new HashMap<>(map1);
    map2.forEach((k,v) -> result.merge(k, v, mergeFunction));
    return result;
}

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

Реализация самой операции слияния тривиальна.

Вы можетееще больше повысить гибкость метода с помощью

public static <K, V> Map<K, V> mergeMaps(
    Map<? extends K, ? extends V> map1, Map<? extends K, ? extends V> map2,
    BiFunction<? super V, ? super V, ? extends V> mergeFunction) {

    Map<K, V> result = new HashMap<>(map1);
    map2.forEach((k,v) -> result.merge(k, v, mergeFunction));
    return result;
}

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

0 голосов
/ 03 июня 2019
/**
 * Test map merge for integer.
 */
public static void testMapMergeForInteger() {
    GenericMap<Integer> genericMap = new GenericMap<>();
    Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
    Map<Integer, Integer> map2 = new HashMap<Integer, Integer>();
    map1.put( 1, 10 );
    map1.put( 2, 20 );
    map2.put( 1, 20 );
    map2.put( 3, 30 );
    map2.put( 4, 40 );
    System.out.println( "Merging of Maps for Integer as value-->\n" + genericMap.merge( map1, map2, (k, v)-> k+v ));
}

public Map<Integer, ? extends Object> merge( Map<Integer, T> m1, Map<Integer, T> m2, 
 BiFunction<T, T, T> func ) {
 Map<Integer, T> re = new HashMap<>( m1 );
    m2.forEach( ( k, v ) -> {
        if ( re.containsKey( k ) ) {
            re.put( k, func.apply( re.get( k ), v ) );
        } else {
            re.put( k, v );
        }
    } );
    return re;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...