Эффективный способ найти, содержит ли карта любой из ключей из списка/iterable

Мне нужно проверить, содержит ли карта какие-либо ключи из списка, и если это так, то вернуть первое соответствующее значение. Наивный подход, который приходит на ум, состоит в том, чтобы сделать это в двух вложенных циклах:

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

Есть ли более приятный и эффективный способ, возможно, основанный на стандартной библиотеке Java?

Ответ 1

Конечно, что-то вроде:

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

Выше всего выполняется только один поиск карты для каждого ключа кандидата. Это позволяет избежать отдельного теста на присутствие плюс извлечение, так как извлечение несуществующего ключа просто даст вам нуль. Обратите внимание (спасибо Slanec), что нулевое значение для действительного ключа неотличимо от несуществующего ключа для этого решения.

Я не совсем понимаю, почему вы выполняете преобразование case, btw.

Ответ 2

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

лучший способ, если нулевые значения, возможно, на карте, и если требуется только первый обнаруженный ключ.

Ответ 3

Мой прием:

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

Ответ 4

В Java 8 вы можете использовать это:

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

Ответ 5

В Java 8 вы можете получить следующее:

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

Если вы просто хотите узнать, является ли какой-либо из кандидатов ключом к карте.

Если вы хотите узнать первое или любое, что вы можете использовать:

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

или

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

Согласно @Klapsa2503 ответ выше

Ответ 6

Try

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

поэтому keySet должен иметь все ключи от HashMap, которые указаны в списке

Ответ 7

Попробуйте как

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

Выход

[1, 3]
1

Ответ 8

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

}

Ответ 9

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