*Markus: HashMap verliert plötzlich alle Werte?

Hallo,

ich habe ein ganz seltsames Problem. In einer HashMap sind alle Daten zuerst vorhanden. Dann übergebe ich diese HashMap-Referenz an eine Methode. In dieser Methode werden die Werte plötzlich irgendwie vernichtet. Die Schlüssel sind noch vorhanden. Wie kann so etwas möglich sein?
Hier ist die komplette Klasse mit zwei eingefügten for-Schleifen, wobei bei der ersten for-Schleife die Werte noch vorhanden sind, bei der zweiten nur mehr die Schlüssel alleine:

  
import java.util.HashMap;  
import javax.swing.table.DefaultTableModel;  
  
public class TelefonTableModel extends DefaultTableModel  {  
  
 @Override  
 public void setValueAt(Object aValue, int row, int column)  {  
  super.setValueAt(aValue, row, column);  
 }  
  
 public void fillTableModelWithData(HashMap<String, String> data)   {  
  for (String element : data.keySet())   {  
      System.out.println("Im Tablemodel: " + element + "," + data.get(element));  
  }  
  
  int i = 0;  
  for (String element : data.keySet())   {  
      super.setValueAt(element, i, 0);  
      super.setValueAt(data.get(element), i, 1);  
      i++;  
     }  
  for (String element : data.keySet())   {  
       System.out.println("Im Tablemodel nach for: " + element + "," + data.get(element));  
  }  
  
  fireTableDataChanged();  
    }  
}  

  1. Hej,

    ich habe ein ganz seltsames Problem. In einer HashMap sind alle Daten zuerst vorhanden. Dann übergebe ich diese HashMap-Referenz an eine Methode. In dieser Methode werden die Werte plötzlich irgendwie vernichtet. Die Schlüssel sind noch vorhanden. Wie kann so etwas möglich sein?

    Was sagt der Debugger? Sind die Schlüssel noch alle da? Sind die Schlüssel auch weg? Sind die values auf null gesetzt? Ändert sich an der kritischen Stelle eventuell der HashCode der keys? Der der values?

    Es ist ganz wichtig, dass Elemente in einer HashMap nicht verändert werden. Wenn sie verändert werden _und_ das führt dazu dass sich der hashCode ändert dann wars das. Die Elemente liegen dann zwar noch in der Map können aber nicht mehr gefunden werden. Aber das wusstest du wahrscheinlich bereits nach Lesen der entsprechenden Lektüre.

    Und: Du zeigst nicht was mit deinen Strings passiert. Diese sind zwar immutable, aber es gibt Hacks die das umgehen.

    Also, entweder mal den Debugger anwerfen und schaun was passiert, oder die Map z.B. in einer Collections.unmodifieableMap() kapseln und schaun ob ne Exception geworfen wird.

    Noch kurz was zu deinem Code:

      
    
    >  public void fillTableModelWithData(HashMap<String, String> data)   {
    
    

    Muss der Übergabewert eine HashMap sein? Map reicht nicht? Wenn es egal ist, sollten immer Typen von Interfaces verwendet werden.

      
    
    >   for (String element : data.keySet())   {  
    >       System.out.println("Im Tablemodel: " + element + "," + data.get(element));  
    >   }
    
    

    Das _kann_ unnötig unperformant sein, besser ist:

      
      for (Map.Entry<String, String> me : data.entrySet())   {  
          System.out.println("Im Tablemodel: " + me.getKey() + "," + me.getValue());  
      }
    

    Beste Grüße
    Biesterfeld

    --
    Art.1: Et es wie et es
    Art.2: Et kütt wie et kütt
    Art.3: Et hätt noch immer jot jejange
    Das Kölsche Grundgesetz
  2. Hallo,

    import java.util.HashMap;
    import javax.swing.table.DefaultTableModel;

    public class TelefonTableModel extends DefaultTableModel  {

    @Override
    public void setValueAt(Object aValue, int row, int column)  {
      super.setValueAt(aValue, row, column);
    }

    public void fillTableModelWithData(HashMap<String, String> data)   {
      for (String element : data.keySet())   {
          System.out.println("Im Tablemodel: " + element + "," + data.get(element));
      }

    int i = 0;
      for (String element : data.keySet())   {
          super.setValueAt(element, i, 0);
          super.setValueAt(data.get(element), i, 1);
          i++;
         }
      for (String element : data.keySet())   {
           System.out.println("Im Tablemodel nach for: " + element + "," + data.get(element));
      }

    fireTableDataChanged();
        }
    }

    zusätzlich zu Biesterfelds Anmerkungen:  
      
    Was hast Du hier vor? Bist Du sicher, dass Du [das Prinzip TableModel](http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#data) verstanden hast?  
      
    Du benötigst hier keine fillTableModelWithData-Methode. Du kannst ein DefaultTableModel per Constructor mit Daten füllen oder Du gibst durch Überschreiben der Methoden  
    public String getColumnName(int col)  
    und  
    public Object getValueAt(int row, int col)  
    vor, woher die Daten kommen sollen.  
      
    Mit der Methode  
    public void setValueAt(Object value, int row, int col)  
    wird dafür gesorgt, dass geänderte Zelldaten aus dem View in den Datenspeicher geschrieben werden können. Sie wird automatisch aufgerufen, wenn sich ein Zellinhalt im View ändert.  
      
    viele Grüße  
      
    Axel
    
    1. Hallo,

      Du benötigst hier keine fillTableModelWithData-Methode. Du kannst ein DefaultTableModel per Constructor mit Daten füllen oder Du gibst durch Überschreiben der Methoden
      public String getColumnName(int col)
      und
      public Object getValueAt(int row, int col)
      vor, woher die Daten kommen sollen.

      Das verstehe ich nicht ganz, denn das TableModel existiert bereits seit langem in der GUI. Da kann ich keinen Konstruktor mehr aufrufen und natürlich könnte ich in der GUI-Klasse die Daten aus der HashMap, die ich aus einer gespeicherten Datei auslese, mit einer for-Schleife einfach ins DefaultTableModel stopfen, aber ich dachte, dass für solche Dinge das Model da ist, und nicht, dass Datenverarbeitungsprozesse in der GUI-Klasse durchgeführt werden.
      Übrigens sind die ganzen "super" in meinem Model gar nicht notwendig. Ich weiß nicht, wie ich dazu kam.
      Desweiteren konnte ich das Problem bereits lösen. Es war gar nicht so einfach, da setValueAt ja die "tableChanged"-Methode aufrief, die wiederum Methoden von meiner Datenspeicherungsklasse unbeabsichtigterweise aufrief und die Inhalte der Value-Werte löschte.
      Trotzdem danke für eure Mühe.

      Markus