Учитывая HashMap, Как отфильтровать его на основе повторяющихся значений в Java - PullRequest
0 голосов
/ 19 июня 2019

У меня есть HashMap, и мне нужно отфильтровать эту карту или создать карту только с ключами, содержащими повторяющиеся значения в данной карте. Пожалуйста, предложите, как мы можем достичь этого?

Просьба учесть, что данный вход является только картой И никакой другой ценности для поиска.

      Map map = new HashMap();
         map.put(1, "abc");
         map.put(2, "def");
         map.put(3, "mno");
         map.put(4, "abc");
         map.put(5, "ijk");
         map.put(6, "abc");

      Map result = new HashMap();
          (1, "abc")
          (4, "abc")
          (6, "abc");

Я ожидаю новую карту, содержащую все ключи со значениями dupliacte

Ответы [ 3 ]

2 голосов
/ 19 июня 2019

Вы можете сделать это с помощью потоков.

Сначала сгруппируйте записи вместе, чтобы записи с одинаковым значением были вместе:

Map<String, Map.Entry<Integer, String>> grouped =
    map.entrySet().stream()
       .collect(groupingBy(Map.Entry::getValue));

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

grouped.values().removeIf(m -> m.size() <= 1);

Затем снова выровнять записи:

Map<Integer, String> result = grouped.values().stream()
    .flatMap(m -> m.entrySet().stream())
    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

Вы также можете сделать это в одном выражении:

Map<Integer, String> grouped =
    map.entrySet().stream()
        .collect(groupingBy(Map.Entry::getValue))
        .values().stream()
        .filter(m -> m.size() > 1)
        .map(Map::entrySet)
        .flatMap(Collection::stream)
        .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
1 голос
/ 19 июня 2019

Вы можете создать карту из значений их частоты

Map<V, Long> counts = map.values().stream()
    .collect(Collectors.groupingBy(
        Function.identity(), Collectors.counting()));

А затем отфильтруйте поток записей исходной карты, сохранив элементы с числом больше 1, и создайте из этого новую карту:

Map<K, V> result = map.entrySet().stream()
    .filter(e -> counts.get(e.getValue()) > 1)
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

Вот пример:

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;

public class RetainFrequentValues
{
    public static void main(String[] args)
    {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "abc");
        map.put(2, "def");
        map.put(3, "mno");
        map.put(4, "abc");
        map.put(5, "ijk");
        map.put(6, "abc");

        // For testing
        map.put(7, "def");

        Map<Integer, String> result = retainFrequentValues(map);
        result.entrySet().forEach(System.out::println);
    }

    private static <K, V> Map<K, V> retainFrequentValues(Map<K, V> map)
    {
        Map<V, Long> counts = map.values().stream()
            .collect(Collectors.groupingBy(
                Function.identity(), Collectors.counting()));
        Map<K, V> result = map.entrySet().stream()
            .filter(e -> counts.get(e.getValue()) > 1)
            .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
        return result;
    }

}
0 голосов
/ 19 июня 2019

Использование коллекции Google в Google:

Импорт:

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Maps;

Использование:

Map<Integer, String> map = new HashMap<>();
map.put(1, "abc");
map.put(2, "def");
map.put(3, "mno");
map.put(4, "abc");
map.put(5, "ijk");
map.put(6, "abc");

HashMultiset<String> ms = HashMultiset.create();
ms.addAll(map.values());
ms.removeIf(e -> ms.count(e) == 1);

Map<Integer, String> result = Maps.filterValues(map, ms::contains);

Результат: {1 = abc, 4 = abc, 6 =abc}

Если Гуава не вариант, см. один из ответов выше.

...