Как добавить уникальные значения в Hashmap для существующего ключа

Я пытаюсь создать программу, в которую я добавляю время выполнения в определенное место. Затем я сохраняю местоположение и время в хэш-карте. Когда я получаю время выполнения, я добавляю его в LinkedList, а затем пытаюсь поместить недавно обновленный LinkedList в значение ключа хэш-карты. Однако, как только я перееду на новое место, время выполнения не останется с заданным местоположением, поэтому у всех мест будет одинаковое время работы. Я не совсем уверен, что я делаю неправильно. Спасибо за любую помощь.

Пример данных: Местоположение A: 45 секунд, 43 секунды, 36 секунд Местоположение B: 51 секунда, 39 секунд

Неверный вывод: Местоположение A: 39 секунд, 51 секунда. Местоположение B: 39 секунд, 51 секунда.

Правильный вывод: Местоположение A: 36 секунд, 43 секунды, 45 секунд Местоположение B: 39 секунд, 51 секунда

    HashMap h = new HashMap();
    LinkedList times = new LinkedList();
    LinkedList newTimes = new LinkedList();


public static void addInformation(HashMap h, LinkedList times, LinkedList    
newTimes) {

   String location = scanner.next();
   Double time = scanner.nextDouble();

   if (h.containsKey(location)){
        for (int i = 0; i < newTimes.size(); i++){
            times.add(newTimes.get(i));
        }
        times.add(time);
        getFastTime(times);
        h.get(location).add(location, times); // cannot resolve add method 
    }else{
        newTimes.clear();
        newTimes.add(time);
        getFastTime(newTimes);
        h.put(location, newTimes);
    }
}
public static void printInformation(HashMap h) {
    Set keySet = h.keySet();  
    for ( Object locationName : keySet) {
        //Use the key to get each value. Repeat for each key.
        System.out.println("Location =" + locationName + " Time =" + 
    h.get(locationName));
    }
}

public static void getFastTime(LinkedList times){
   times.sort(null);
}

3 ответа

Решение

Проблема в том, что Java проходит по ссылке. Вы не создаете новые списки для разных мест, поэтому один и тот же список используется для всех записей на карте. Вы должны прочитать об этом, потому что это фундаментальный аспект Java.

Далее ваши коллекции должны быть параметризованы. Вам не нужны времена и новые списки времени. Также используйте Список, а не LinkedList на карте. Примерно так:

HashMap<String, List<Double>> map = new HashMap<>();

И сделать то же самое в определениях методов. Существует ряд других проблем, таких как метод printInformation, который предполагает, что Объекты являются Строками, даже не приводя их в соответствие. Ввод не подтвержден. Что если вход неверен? Это следует учитывать. Кроме того, переменные должны быть названы лучше.

Нечто подобное должно работать (не проверено. Вам также придется взглянуть на метод print, чтобы он работал со списком):

HashMap<String, List<Double>> map = new HashMap<>();

public static void addInformation(HashMap<String, List<Double>> map) {
    //input should be validated here
    String location = scanner.next();
    Double time = scanner.nextDouble();

    List<Double> timesInMap = map.get(location);
    if (timesInMap != null){
        timesInMap.add(time);
        timesInMap.sort(null);
    }else{
        timesInMap = new ArrayList<Double>();
        timesInMap.add(time);
        map.put(location, timesInMap);
    }
}
public static void printInformation(HashMap<String, List<Double>> map) {
    Set<String> keySet = map.keySet();  
    for (String locationName : keySet) {
        //Use the key to get each value. Repeat for each key.
        System.out.println("Location =" + locationName + " Time =" + 
                map.get(locationName));
    }
}

В Java, когда вы передаете параметр или получаете объект, вы фактически обрабатываете ссылку на этот объект. В основном, коллекции являются изменяемыми (даже если вы можете создавать неизменяемые тоже), то есть вы можете изменить коллекцию на месте. Предпочтительно использовать Generics для поддержки строгой типизации, и это должно решить вашу проблему add метод не решен.

Например, hashmap должен быть объявлен как:

HashMap<String, List<Double>> h = new HashMap<>();

С левой стороны, он только объявляет, что должно содержать hashmap, нет List<Double> еще не создан.

Я не уверен, что вам нужно глобально объявить times а также newTimes списки. Значения времени будут храниться в разных List<Double> для каждой записи в HashMap<>, addInformation Функция может иметь следующую логику:

// Add one (location, time) scanned from input
public static void addInformation(HashMap<String, List<Double> locations,
                                  Scanner scanner) {
   String location = scanner.next();
   Double time = scanner.nextDouble();

   List<Double> times = locations.get(location);
   if (times == null) {
      // this is a new location, create the linkedlist
      // and put it in the hashmap
      times = new LinkedList<Double>();
      locations.put(location, times);
   }
   // add the time to the linkedlist
   times.add(time);
}

В вышеупомянутой реализации времена упорядочены путем вставки (первый элемент был вставлен первым). Если вы хотите, чтобы значения этого времени всегда сортировались, вы можете сортировать список каждый раз, когда добавляете новое (местоположение, время), т.е. добавляйте следующую строку сразу после times.add(time):

Collections.sort(times);

Сортировка изменяет список - вы можете получить более подробную информацию в java doc Collections.sort.

Другой вариант заключается в использовании TreeSet<Double> вместо LinkedList<Double>, Элементы будут сохранены отсортированными, но дублирование времени не допускается.

Если вам нужно сохранить дубликаты значений времени и отсортированную коллекцию, то у вас есть TreeMultiset, который делает именно это.

Также учтите, что порядок либо с Collection.sort или с отсортированной коллекцией, как TreeSet можно контролировать с помощью Comparator, Например, вы можете хотеть иметь время в порядке убывания (естественный порядок будет увеличиваться для Double).

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

HashMap h = new HashMap();
public static void addInformation(HashMap h, LinkedList times, LinkedList    
newTimes) {

   String location = scanner.next();
   Double time = scanner.nextDouble();

   if (h.containsKey(location)){
        LinkedList times = h.get(location);
        times.add(time);
        getFastTime(times);

    }else{
        LinkedList newTimes = new LinkedList();
        newTimes.add(time);
        getFastTime(newTimes);
        h.put(location, newTimes);
    }
}
Другие вопросы по тегам