Проверьте, существует ли значение ключа в hashmap

У меня есть HashMap, где ключ - это вид птицы, а значение - количество восприятий. Вот мой код:

public class Program {

public static void main(String[] args) {

    HashMap<String, Integer> species = new HashMap<>();
    Scanner reader = new Scanner(System.in);

    species.put("hawk (buteo jamaicensis)", 2);
    species.put("eagle (aquila chrysaetos)", 4);
    species.put("sparrow (passeridae)", 5);

    System.out.println("What specie?"); //output "chicken"
    String specie = reader.nextLine();

    for (HashMap.Entry<String, Integer> entry: species.entrySet()) {
        if (entry.getKey().contains(specie)) {
            System.out.println(entry.getKey()+" : "+entry.getValue()+" perceptions");
        } else {
            System.out.println("Not in database!");
        }
    } 
}

}

Как я могу проверить, существует ли вид в hashmap? Например, если выводится «цыпленок» и его нет в базе данных, программа должна напечатать «Нет в базе данных!». Теперь вывод:

Not in database!
Not in database!
Not in database!

И моя цель:

Not in database!

Почему вы перебираете все записи HashMap, если можно просто вызвать containsKey?

rgettman 14.03.2018 20:33

почему бы просто не вызвать map.get и проверить, существует ли возвращаемое значение

John Kane 14.03.2018 20:34

Где вы видите здесь "курицу": species.put("hawk (buteo jamaicensis)", 2); species.put("eagle (aquila chrysaetos)", 4); species.put("sparrow (passeridae)", 5);?

davidxxx 14.03.2018 20:36

@davidxxx Вот почему ожидаемый результат - «Нет в базе данных!»

Bernhard Barker 14.03.2018 20:37

Многие люди, похоже, упускают тот факт, что OP (по-видимому, намеренно) проверяет, содержит ли каждый ключ String входную строку, а не просто проверяет, равны ли они.

Bernhard Barker 14.03.2018 20:40

@Dukeling В любом случае, это бессмысленно. Если OP добавляет на карту три записи, мы ожидаем, что в любом случае будет 3 println. Я голосую за закрытие.

davidxxx 14.03.2018 20:41

@Dukeling, какой смысл проверять, присутствует ли ключ подстроки на карте, и отвечать с этим? Я думаю, вы упускаете суть.

NiVeR 14.03.2018 20:42

Примечание: «виды» - единственное число от «видов».

Bernhard Barker 14.03.2018 21:16

Вы должны пересмотреть: обязательно ли доступ к вашей хэш-карте использовать полное имя (обычный английский плюс латинский), или просто общее имя, или, может быть, только латинское имя? Возможно, вы захотите сопоставить и английское, и латинское имя с объектом Bird, где вы сохраните оба термина (и, возможно, больше) в качестве полей.

laune 14.03.2018 21:25

Обратите внимание, что даже латинские имена не являются тем, что демонстрирует ваш пример. Воробей может быть «домашним прохожим» или «прохожим монтанусом» - так что же должна делать ваша процедура поиска?

laune 14.03.2018 21:29
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
10
3 015
3

Ответы 3

Используйте для этого логический флаг:

boolean found = false;
for (HashMap.Entry<String, Integer> entry: species.entrySet()) {
        if (entry.getKey().contains(specie)) {
            System.out.println(entry.getKey()+" : "+entry.getValue()+" perceptions");
            found = true;
        }
} //Loop ends
if (!found) {
        System.out.println("Not in database!");
}

Вы также можете использовать для этого Потоки Java 8: (хотя я бы, вероятно, просто рекомендовал вместо этого цикл for)

Optional<Map.Entry<String, Integer>> match = 
      species.entrySet().stream().filter(entry -> entry.getKey().contains(specie)).findAny();
if (match.isPresent())
   System.out.println(match.get().getKey()+" : "+match.get().getValue()+" perceptions");
else
   System.out.println("Not in database!");

.stream превращает набор записей в поток. .filter удаляет все, кроме элемента, который мы ищем. .findAny возвращает элемент, если он существует.


Хотя, если вы просматриваете карту в цикле, чтобы найти то, что ищете, это подрывает цель карты, и вы можете выбрать список какого-то настраиваемого класса, разделив строку на 2, а затем имея ключом может быть общепринятое английское имя (как рекомендовано в комментариях) или использование более сложной структуры данных, которая позволяет осуществлять эффективный поиск подстроки, например суффиксное дерево.

Я думаю, что стримы для этого - излишество.

if (species.containsKey(selectedSpecie)) {
   return species.get(selectedSpecie);
} else {
  throw new IllegalStateException("Not in database!");
}

Другие вопросы по теме