Поиск совпадающих ключей и значений на карте

#java #map #iterator #set

#java #словарь #итератор #установить

Вопрос:

В этой задаче мне нужно найти все совпадающие сопоставления ключей и значений в двух картах, а затем вернуть их на новую карту, но я сталкиваюсь с некоторыми проблемами. Моя идея состоит в том, чтобы найти все совпадающие ключи из двух карт, а затем использовать эти ключи для ссылки на значения. Если бы значения совпадали, я бы поместил ключ / значение в карту. Я пытаюсь выяснить, почему он просто добавляет все общие ключи; он добавляет эти ключи только в том случае, если его соответствующие значения тоже совпадают. Спасибо.

Приглашение:

Напишите метод intersect, который принимает два отображения строк в целые числа в качестве параметров и возвращает новое отображение, содержимое которого является пересечением двух. Пересечение двух карт определяется здесь как набор ключей и значений, которые существуют в обеих картах. Итак, если какой-то ключ K сопоставляется со значением V как в первой, так и во второй карте, включите его в свой результат. Если K не существует в качестве ключа в обеих картах или если K не соответствует одному и тому же значению V в обеих картах, исключите эту пару из вашего результата. Например, рассмотрим следующие две карты:

 {Janet=87, Logan=62, Whitaker=46, Alyssa=100, Stefanie=80, Jeff=88, Kim=52, Sylvia=95}
{Logan=62, Kim=52, Whitaker=52, Jeff=88, Stefanie=80, Brian=60, Lisa=83, Sylvia=87}
  

Вызов вашего метода на предыдущих картах вернет следующую новую карту (порядок пар ключ / значение не имеет значения):

 {Logan=62, Stefanie=80, Jeff=88, Kim=52}
  

Мой код:

 // we need to store the keys, then get the values in common, then put the key/map into map
public static Map<String, Integer> intersect(Map<String, Integer> first, Map<String, Integer> second) {
    Map<String, Integer> output = new HashMap<String, Integer>(first); // combined output
    Set<String> keyFirst = new HashSet<String>(); // stores all the keys for first
    for (String key: first.keySet()) { // goes through each key in input
        keyFirst.add(key); // adds all keys from first into keyFirst
    }

    // goes through each key in common and checks to see if they reference to the same value
    Iterator<String> keyFirstItr = keyFirst.iterator();
    while (keyFirstItr.hasNext()) {
        String keyTemp = keyFirstItr.next();
        if (first.get(keyTemp) == second.get(keyTemp)) { // If same key, same value mapped
            output.put(keyTemp, first.get(keyTemp)); // add key value to map
        }
    }
    return output;
}
  

Комментарии:

1. В чем ваш вопрос? С чем вы сравниваете объекты == ?

2. Я пытаюсь выяснить, почему он просто добавляет все общие ключи.

3. Это не вопрос. Это подтверждение. Вопрос заканчивается вопросительным знаком.

Ответ №1:

Вы помещаете все значения из первого в выходной, передавая его конструктору.

 Map<String, Integer> output = new HashMap<String, Integer>(first); // you are passing first to the constructor.
  

Вам не нужно создавать другой набор, метод keySet() возвращает set, поэтому приведенные ниже строки не требуются.

 Set<String> keyFirst = new HashSet<String>(); // stores all the keys for first
    for (String key: first.keySet()) { // goes through each key in input
        keyFirst.add(key); // adds all keys from first into keyFirst
}
  

Вот правильная реализация.

 // we need to store the keys, then get the values in common, then put the key/map into map
public static Map<String, Integer> intersect(Map<String, Integer> first, Map<String, Integer> second) {
    Map<String, Integer> output = new HashMap<String, Integer>(); // combined output

    // goes through each key in common and checks to see if they reference to the same value    
    Iterator<String> keyFirstItr = first.keySet().iterator();
    while (keyFirstItr.hasNext()) {
        String keyTemp = keyFirstItr.next();
        if (first.get(keyTemp).equals(second.get(keyTemp))) { // If same key, same value mapped
            output.put(keyTemp, first.get(keyTemp)); // add key value to map
        }
    }
    return output;
}
  

Комментарии:

1. Скажите ему, чтобы он также использовал equals , а не == !

2. get возвращает значение, которое является целым числом, поэтому == будет работать

3. @AmitChotaliya: нет, этого не произойдет. == проверяет, указывают ли две ссылки на один и тот же объект. new Integer(1) == new Integer(1) равно false.

4. @Seelenvirtuose amp; JB Nizet вы правы, я изменю ответ. Разве это не должно выполнять автоматическую упаковку / распаковку здесь?

5. Спасибо за помощь. В книге, которую я имею, говорится, что распаковка происходит автоматически и что «Java понимает взаимосвязь между in и Integer, она развернет для вас целочисленные объекты и предоставит вам значения int, хранящиеся внутри». Приведенный пример был: int product = list.get(0) * list.get(1);

Ответ №2:

Более простое решение этого упражнения — пропустить итератор и использовать цикл for, как показано ниже. Для каждого имени в map1 мы проверяем, существует ли оно в map2 и совпадают ли значения. Затем K и V добавляются к новой карте:

 public static Map intersect(Map<String, Integer> map1, Map<String, Integer> map2){
    Map<String, Integer> newMap = new HashMap<>();
    for (String name : map1.keySet()){
        if(map2.containsKey(name) amp;amp; map1.get(name).equals(map2.get(name))){
            newMap.put(name, map1.get(name));
        }
    }
    return newMap;        
}