Nano Hash - криптовалюты, майнинг, программирование

Функция HashMap «положить» не работает должным образом - Java

Я читаю CSV и сохраняю данные в объекты (объект создается для каждой строки). Строки в CSV сгруппированы по первому элементу (номер группы) - где-то между 2-10 строками есть общий номер группы. В наборе данных ~ 180 групп. Чтобы упростить обработку этих данных, я сохраняю данные в HashMaps, где ключ — это номер группы, а значение, привязанное к ключу, — это ArrayList объектов данных.

Когда я перебираю строки CSV, я добавляю объекты в HashMap, используя номер группы строк, чтобы указать, куда поместить новый объект данных. Если у объекта есть номер группы, который еще не был введен в CSV, он создает новый ключ (его номер группы) и список объектов данных ArrayList, содержащий только себя.

Если номер группы строки ЯВЛЯЕТСЯ ключом в HashMap, он получает ArrayList, привязанный к номеру группы, добавляет к нему новый объект данных и использует функцию put для повторного добавления новой записи с обновленным ArrayList (теперь с еще одна запись данных, привязанная к общему номеру группы).

Пример кода:

  ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
  HashMap<Integer,ArrayList<CSVData>> CSVDataMapNew = new HashMap<Integer,ArrayList<CSVData>>();
  while ((line = reader.readLine()) != null && !(line.contains(",,,,,,,,,"))) 
{
            System.out.println(line);
            String[] csvDataNew = line.split(",");
            String currentGroup = csvDataNew[GroupIndex];
            try {
                currentGroupNumber = Integer.parseInt(currentGroup.replace("group", "").replace(" ", ""));
            } catch (Exception ex) {
                currentGroupNumber = previousGroupNumber;
            }
            String path = csvDataNew[PathIndex];
            startLine = Integer.parseInt(csvDataNew[StartLineIndex]);
            endLine = Integer.parseInt(csvDataNew[EndLineIndex]);

            CSVData data = new CSVData(currentGroupNumber, path, startLine, endLine);

            if (CSVDataMapNew.containsKey(currentGroupNumber)) { //if it does contain the current key, add the current object to the ArrayList tied to it.
                csvListNew = CSVDataMapNew.get(currentGroupNumber);
                csvListNew.add(clone);
                CSVDataMapNew.put(currentGroupNumber, csvListNew);
            } else { //if it doesnt contain the current key, make new entry
                csvListNew.add(clone);
                CSVDataMapNew.put(currentGroupNumber, csvListNew);
                System.out.println(CSVDataMapNew.size());
                System.out.println(CSVDataMapNew.get(currentGroupNumber).size());
            }
            csvListNew.clear(); //to make sure no excess objects are entered into the map.
            previousGroupNumber = currentGroupNumber;
        }

Существуют соответствующие попытки перехвата и т. д., а CSVDataTable объявлен в своем собственном классе, на который ссылаются статически.

Проблема в том, что когда я добавляю операторы печати на каждом этапе, каждый ArrayList в HashMap стирается в конце каждого цикла. Таким образом, как только CSV завершается, он имеет значение каждого ключа, но все ArrayLists, привязанные к каждому ключу, пусты. (Доказано последующим циклическим просмотром HashMap).

Как я могу решить эту проблему, поэтому, когда я ввожу значение в ArrayList и повторно «помещаю» ключ и обновленный ArrayList в карту, он сохраняет свои данные?

11.07.2017

  • Измените csvListNew.clear(); на csvListNew = new ArrayList<CSVData>();. Как у вас сейчас, вы каждый раз помещаете один и тот же список на карту. И вы каждый раз очищаете его в конце цикла. 11.07.2017
  • Ваш код трудно читать. Почему вы написали один объект CSVDataMapNew с большой буквы? Создается впечатление, что вы работаете со статическим классом. 11.07.2017
  • Проблема в том, что когда я добавляю операторы печати на каждом этапе, каждый ArrayList в HashMap стирается в конце каждого цикла. - ну да, вы звоните clear() по списку, чью ссылку вы только что вставили в карту... 11.07.2017
  • @rabbitguy Я добавил объявление CSVDataMapNew в вопрос, чтобы было все необходимое для понимания моего кода. На самом деле это статический объект в другом классе, но это было просто для того, чтобы люди, отвечающие на мой вопрос, могли видеть все соответствующие фрагменты кода. 12.07.2017

Ответы:


1

Вы всегда помещаете один и тот же экземпляр ArrayList в качестве значения в свой HashMap. Это экземпляр ArrayList, созданный перед циклом, на который ссылается переменная csvListNew.

Это означает, что когда вы вызываете csvListNew.clear(), вы очищаете все ArrayList из вашего HashMap.

Это можно исправить, создавая новый ArrayList каждый раз, когда вы хотите поместить новую запись в свой HashMap:

        if (CSVDataMapNew.containsKey(currentGroupNumber)) {
            csvListNew = CSVDataMapNew.get(currentGroupNumber);
            csvListNew.add(clone);
        } else {
            csvListNew = new ArrayList<>(); // that's the main required fix
            csvListNew.add(clone);
            CSVDataMapNew.put(currentGroupNumber, csvListNew);
            System.out.println(CSVDataMapNew.size());
            System.out.println(CSVDataMapNew.get(currentGroupNumber).size());
        }

Кроме того, удалите вызов csvListNew.clear().

11.07.2017

2

Таким образом, как только CSV завершается, он имеет значение каждого ключа, но все ArrayLists, привязанные к каждому ключу, пусты. (

Этот

  ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();

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

И в конце вашего метода вы делаете:

 csvListNew.clear(); 

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

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

  ArrayList<CSVData> csvListNew = CSVDataMapNew.get(currentGroupNumber);

  if (csvListNew == null) 
     csvListNew = new ArrayList<CSVData>();
     CSVDataMapNew.put(csvListNew);
  }

Затем повторно используйте переменную csvListNew, чтобы добавить элемент в:

 csvListNew.add(clone);

Это упрощает ваш фактический код, который имеет нежелательное дублирование.

11.07.2017

3

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

  • Вам не нужно возвращать список обратно на карту после того, как вы что-то добавили в него.
  • Вы должны создать новый список для каждой записи карты. В настоящее время вы этого не делаете.

Это должно исправить это (также скорректированный стиль кода):

    Map<Integer,List<CSVData>> CSVDataMapNew = new HashMap<>();
    while ((line = reader.readLine()) != null && !(line.contains(",,,,,,,,,")))
    {
        System.out.println(line);
        String[] csvDataNew = line.split(",");
        String currentGroup = csvDataNew[GroupIndex];
        try {
            currentGroupNumber = Integer.parseInt(currentGroup.replace("group", "").replace(" ", ""));
        } catch (Exception ex) {
            currentGroupNumber = previousGroupNumber;
        }
        String path = csvDataNew[PathIndex];
        startLine = Integer.parseInt(csvDataNew[StartLineIndex]);
        endLine = Integer.parseInt(csvDataNew[EndLineIndex]);

        CSVData data = new CSVData(currentGroupNumber, path, startLine, endLine);

        if (CSVDataMapNew.containsKey(currentGroupNumber)) { 
            CSVDataMapNew.get(currentGroupNumber).add(clone);
        } else { 
            ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
            CSVDataMapNew.put(currentGroupNumber, csvListNew);
            csvListNew.add(clone);
        }
        previousGroupNumber = currentGroupNumber;
    }
11.07.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..