web-dev-qa-db-fra.com

Moyen efficace de rechercher si la carte contient l'une des clés d'une liste/itérable

Je dois vérifier si map contient l'une des clés d'une liste et si elle renvoie la première valeur correspondante. L’approche naïve qui nous vient à l’esprit est de le faire en deux boucles imbriquées:

Map<String, String> fields = new HashMap<String, String>();
fields.put("a", "value a");
fields.put("z", "value z");
String[] candidates = "a|b|c|d".split("|");
for (String key : fields.keySet()){
    for (String candidate : candidates) {
        if (key.equals(candidate)){
            return fields.get(key);
        }
    }
}

Existe-t-il un moyen plus agréable et plus efficace, éventuellement basé sur la bibliothèque standard Java?

9
ccpizza

Sûrement quelque chose comme:

for (String candidate : candidates) {
     String result = fields.get(key);
     if (result != null) {
         return result;
     }
}

Ce qui précède effectue uniquement un recherche de carte par clé candidate. Cela évite le test séparé pour la présence et l'extraction, car l'extraction d'une clé inexistante vous donnera simplement un zéro. Notez (merci Slanec ) qu’une valeur nulle pour une clé valide est impossible à distinguer d’une clé inexistante pour cette solution.

Je ne comprends pas très bien pourquoi vous effectuez la conversion de cas, au fait.

20
Brian Agnew
for(String candidate : candidates) {
 if(fields.containsKey(candidate)) {
  return fields.get(candidate)
 }
}

le meilleur moyen si des valeurs nulles sont éventuellement dans map et si seule la première clé détectée est requise. 

23
NimChimpsky

Ma prise

Map<String, String> fields = new HashMap<String, String>();
fields.put("a", "value a");
fields.put("z", "value z");
String[] candidates = "a|b|c|d".split("|");
for (String candidate : candidates) {
    if (fields.containsKey(candidate)) {
        return fields.get(candidate);
    }
}
7
Petr Janeček

En Java 8, vous pouvez avoir ceci:

boolean exists = Arrays.stream(candidates).anyMatch(fields::containsKey);

Si vous voulez juste savoir si l'un des candidats est la clé de la carte.

Si vous voulez connaître le premier ou tous ceux que vous pouvez utiliser:

Arrays.stream(candidates).filter(fields::containsKey).findAny();

ou

Arrays.stream(candidates).filter(fields::containsKey).findFirst();

Selon la réponse @ Klapsa2503 ci-dessus

6
mrossini

En Java 8, vous pouvez utiliser ceci:

return candidates.stream()
            .filter(fields::containsKey)
            .findFirst()
            .map(fields::get)
            .orElse(null);
5
Klapsa2503

Essayer

Set<String> keySet = new HashSet<String>(fields.keySet());    
keySet.retainAll(list);

alors keySet est supposé avoir toutes les clés de HashMap qui sont mentionnées dans la liste

5
Nikolay Kuznetsov

Essayez comme

    List list= Arrays.asList(1, 2, 3);
    HashMap map = new HashMap();
    map.put(1, 1);
    map.put(3, 3);
    Set set = new HashSet(map.keySet());
    set.retainAll(list);
    System.out.println(set);
    Object e = set.isEmpty() ? null : set.iterator().next();
    System.out.println(e);

sortie

[1, 3]
1
2
Evgeniy Dorofeev
Map<String, String> fields = new HashMap<String, String>();
fields.put("a", "value a");
fields.put("z", "value z");
String[] candidates = "a|b|c|d".split("|");
List<String> canList = Arrays.asList(candidates );
for (String key : fields.keySet()){

if (canList .contains(key)) {
return fields.get(key);
}

}
1
NPKR

Vous pouvez utiliser une seule boucle si vous supposez que la clé de la carte est déjà en minuscule, de la même manière que vous supposez que les valeurs de recherche sont en minuscule.

1
Peter Lawrey