2017-07-11 11 views
0

Ich lese durch eine CSV und speichern die Daten in Objekte (ein Objekt wird für jede Zeile erstellt). Die Zeilen in der CSV werden nach dem ersten Element (Gruppennummer) gruppiert - irgendwo zwischen 2-10 Zeilen teilen sich eine Gruppennummer. Es gibt ~ 180 Gruppen im Datensatz. Um diese Daten leichter zu verarbeiten, speichere ich die Daten in HashMaps, wobei der Schlüssel die Gruppennummer ist und der Wert, der mit dem Schlüssel verknüpft ist, eine ArrayList der Datenobjekte ist.HashMap Funktion 'put' funktioniert nicht richtig - Java

Während ich durch die CSV-Zeilen iteriere, füge ich der HashMap Objekte hinzu und verwende die Gruppennummer der Zeile, um zu bestimmen, wo das neue Datenobjekt abgelegt werden soll. Wenn das Objekt eine Gruppennummer hat, die noch nicht in die CSV-Datei eingegeben wurde, erstellt es einen neuen Schlüssel (seine Gruppennummer) und eine ArrayList mit Datenobjekten, die nur sich selbst enthalten.

Wenn die Gruppennummer der Zeile ein Schlüssel in der HashMap ist, wird die ArrayList an die Gruppennummer gebunden, das neue Datenobjekt hinzugefügt und die put -Funktion verwendet, um den neuen Eintrag erneut hinzuzufügen ArrayList (jetzt mit einem weiteren Dateneintrag, der an die freigegebene Gruppennummer gebunden ist).

Code-Beispiel:

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

Es gibt entsprechende Try-Fänge usw. und die CSVDataTable in seiner eigenen Klasse deklariert, statisch verwiesen wird.

Das Problem ist, wenn ich Druckanweisungen bei jedem Schritt hinzufüge, wird es wie jede ArrayList in der HashMap am Ende jeder Schleife gelöscht. Sobald die CSV-Datei fertiggestellt ist, hat sie also alle Schlüsselwerte, aber die mit jedem Schlüssel verknüpften ArrayLists sind alle leer. (Evidenced durch Schleifen durch die HashMap nachher).

Wie kann ich dies lösen, wenn ich also einen Wert in die ArrayList eingib und den Schlüssel und die aktualisierte ArrayList in die Map lege, behält sie ihre Daten?

+0

ändern 'csvListNew.clear();' auf 'csvListNew = new Arraylist ();'. So wie Sie es jetzt haben, legen Sie jedes Mal dieselbe Liste in die Karte. Und Sie löschen es jedes Mal am Ende Ihrer Schleife. –

+0

Ihr Code ist schwer zu lesen. Warum haben Sie das eine Objekt 'CSVDataMapNew' großgeschrieben? Es sieht so aus, als ob Sie mit einer statischen Klasse arbeiten. –

+2

"Das Problem ist, wenn ich in jedem Schritt Druckanweisungen hinzufüge, wird es wie jede ArrayList innerhalb der HashMap am Ende jeder Schleife gelöscht." - Nun ja, du nennst 'clear()' auf der Liste, deren Referenz du gerade in die Map gelegt hast ... –

Antwort

1

Sie setzen immer die gleiche ArrayList Instanz als Wert in Ihre HashMap. Das ist die ArrayList Instanz, die vor der Schleife erstellt und von der csvListNew-Variable referenziert wird.

Das heißt, wenn Sie csvListNew.clear() aufrufen, löschen Sie alle ArrayList s Ihrer 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()); 
     } 

Außerdem entfernen Sie den csvListNew.clear() Aufruf:

Dies kann durch die Schaffung ein neues ArrayList jedes Mal, wenn Sie in Ihrem HashMap einen neuen Eintrag setzen wollen fixiert werden.

2

Also, wenn die CSV durch iteriert beendet wird, hat es jede Taste Wert, aber die Arraylisten zu jedem Schlüssel gebunden sind alle leer. (

Diese

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

sollte jede Taste Ihrer Karte aufgerufen und verknüpft werden.
Aber Sie verwenden, um eine einzelne Instanz der ArrayList als Wert für jeden Schlüssel Ihrer Karte.

Und am Ende Ihrer Methode, die Sie tun:

csvListNew.clear(); 

Also alle Ihre Werte Ihrer Karte sind eine leere ArrayList als alle bezieht sich auf die gleiche ArrayList.

Ihr Problem lösen, wenn der Schlüssel Sie eine neue Arraylist erstellen sollten nicht in der Karte vorhanden ist und es zu diesem Schlüssel zuordnen:

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

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

dann die csvListNew Variable Wiederverwendung in das Element hinzuzufügen:

csvListNew.add(clone); 

Es vereinfacht Ihren tatsächlichen Code, der unerwünschte Duplizierung hat.

1

Wenn Sie eine Liste von einer HashMap erhalten, erhalten Sie einen Verweis auf die Liste. Alles, was Sie anschließend mit dieser Liste tun, wirkt sich auf die Liste in der Karte aus. Das bedeutet zweierlei:

  • Sie müssen nicht zurück in die Karte, um die Liste zu setzen, nachdem Sie eine neue Liste für jeden Map-Eintrag etwas, um es
  • Sie haben erstellen hinzugefügt. Das machst du momentan nicht.

Dies sollte es beheben (auch einige angepasste Code-Stil):

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; 
    } 
Verwandte Themen