J'ai un HashMap et je dois filtrer cette carte ou créer une carte uniquement avec des clés contenant des valeurs en double dans la carte donnée. Veuillez suggérer comment pouvons-nous y parvenir?

Veuillez noter que l'entrée donnée n'est que la carte. Et aucune autre valeur à rechercher.

      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");

J'attends une nouvelle carte contenant toutes les clés avec des valeurs en double

0
M Krishna 19 juin 2019 à 18:16

3 réponses

Meilleure réponse

Vous pouvez créer une carte des valeurs à leur fréquence

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

Ensuite, filtrez le flux d'entrées de la carte d'origine, en conservant les éléments qui ont un nombre supérieur à 1, et créez une nouvelle carte à partir de cela:

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

Voici un exemple:

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;
    }

}
1
Marco13 19 juin 2019 à 15:52

Vous pouvez le faire en utilisant des flux.

Tout d'abord, regroupez les entrées afin que les entrées avec la même valeur soient ensemble:

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

Supprimez ensuite les entrées où il n'y avait qu'une seule occurrence de la valeur:

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

Ensuite, aplatissez à nouveau les entrées:

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

Vous pouvez également le faire dans une seule expression:

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));
2
Andy Turner 19 juin 2019 à 18:11

Tirer parti de la collection Guava de Google:

Importation:

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

Usage:

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);

Le résultat: {1 = abc, 4 = abc, 6 = abc}

Si Guava n'est pas une option, veuillez voir l'une des réponses ci-dessus.

0
phil_g 19 juin 2019 à 16:30