# Probleme mit collection.containsAll



## Stefan79 (17. Dez 2007)

Hallo
ich habe zwei Collections die ich miteinander vergleichen möchte. Das Ganze probiere ich so:

```
collection1.containsAll(collection2);
```
Nur leider scheint das nicht zu funktionieren. Mache ich irgendwas falsch oder kennt ihr einen anderen, vielleicht auch besseren weg zwei collections miteinander zu vergleichen.
Wäre sehr wichtig damit ich mit meinem Programm weiter machen kann, Danke


----------



## Wildcard (17. Dez 2007)

Ich kann dir versichern das containsAll genau das macht, was in der API-Doc beschrieben ist.


----------



## Verjigorm (17. Dez 2007)

was "scheint denn nicht zu funktionieren" ?
gehts nicht genauer?


----------



## Stefan79 (17. Dez 2007)

Also in Collection1 steht eingetragen, geändert und in Collection2 steht auch eingetragen, geändert
Dann frage ich ab:

```
if (container1.containsAll(container2)
{
   system.out.println("is containing");
   tueEtwas();
}
```
Und da meine Ausgabe nicht angezeigt wird, kann ich ja davon ausgehen, dass mit containsAll false zurück liefert obwohl beide collections identischen Inhalt besitzen.
Gibt es denn noch eine andere Möglichkeit, die ich mal ausprobieren könnte?
Oder an was könnte es denn liegen, habe mir beide collections auch schon ausgeben lassen und da steht wirklich in beiden das gleiche.


----------



## Wildcard (17. Dez 2007)

Speicherst du dort Referenzen auf Objekte eigener Klassen und hast dort equals und hashCode nicht richtig überschrieben?


----------



## Stefan79 (17. Dez 2007)

mhh...ich hole mir die Collections aus einer Map, weiß nicht ob das irgendwelche Auswirkungen auf containsAll hat:

```
Collection collection1 = (Collection)aMap.get(col1);
Collection collection2 = (Collection)aMap.get(col2);
if(collection1.containsAll(collection2)
{
    tueEtwas();
}
```
Die Collections werden an anderer Stelle schon als Collections in der Map gespeichert


----------



## Wildcard (17. Dez 2007)

Das beantwortet die Frage nicht. Auf den Inhalt kommt es an.


----------



## Stefan79 (17. Dez 2007)

Nein es werden keine Referenzen in der Collection gespeichert, sondern reine Strings.
Gäbe es denn eine andere Möglichkeiten Collections mit geringem Aufwand zu vergleichen?


----------



## Wildcard (17. Dez 2007)

Das sind dann trotzdem Referenzen, eben auf String Objekte.
Ich behaupte das der Inhalt eben nicht identisch ist, sonst würde es mit Strings funktioneren (da dort equals und hashCode korrekt implementiert ist).


----------



## Stefan79 (17. Dez 2007)

Hab es jetzt überprüft, der Hashcode ist ein anderer. Was muss ich da denn jetzt machen um die beiden Collections trotzdem vergleichen zu können?? WIe kann ich den HashCode überschreiben??


----------



## Marco13 (17. Dez 2007)

Wenn der HashCode unterschiedlich ist, sind auch die Collections unterschiedlich. (Umgekehrt gilt das nicht unbedingt, aber das nur nebenbei....). 

Du hättest die Frage wohl nie gestellt, wenn du mal versucht hättest, ein kleines, selbstständig compilierbares, lauffähiges Beispiel zu posten, wo der "Fehler" auftritt. Das wäre dir nämlich nicht gelungen (und du hättest gemerkt, dass der Fehler bei dir liegt) oder man hätte dir sofort gesagt, wo in deinem kleinen, selbstständig compilierbaren, lauffähigen Beispiel der Fehler ist.


----------



## maki (17. Dez 2007)

Stefan79 hat gesagt.:
			
		

> Hab es jetzt überprüft, der Hashcode ist ein anderer. Was muss ich da denn jetzt machen um die beiden Collections trotzdem vergleichen zu können?? WIe kann ich den HashCode überschreiben??


Irgendetwas machst du falsch.

Zwei String sind "equal", wenn sie den selben Text enthalten.
Wenn zwei Strings "equal" sind, dann haben sie den selben Hashcode.


----------



## Stefan79 (17. Dez 2007)

OK ihr habt recht sollte vielleicht mal den ganzen Code posten damit mir geholfen werden kann:

```
for(int i = 0; i < iTableModel.getRowCount();i++)
	      {
                String tKey = iTableModel.getValueAt(i,0);
	        Collection tCollection = (Collection) iTableModel.getValueAt(i,1);
                
                if (! tCollection.isEmpty())
                {
                      tMap.put(tKey, tCollection);
                 }
               }
// weiter unten im Code

List tKeyList = getSeparatedListString (tAvailableKeys) //liefert kommaseparierte Liste
for ( int i = 0; i < tKeyList.size(); i++)
{
    Collection tColl1 = (Collection)tMap.get(tKeyList.get(i));
    Collection tColl2 = (Collection) tMap.get(tKeyList.get(i));

    if ( tColl1.containsAll(tColl2))
    {
        tueEtwas();
    }
}
```
Ich hole mir also über den key die einzelnen Collections wieder heraus und möchte rein den Inhalt vergleichen, HashMap oder so interessiert mich nicht, scheinbar geht dies ja nicht über containsAll oder doch?
Wie kann ich es sonst noch lösen??


----------



## Wildcard (17. Dez 2007)

Und wieder weigerst du dich beharrlich zu zeigen wo und wie deine Collections denn nun befüllt werden


----------



## Stefan79 (17. Dez 2007)

Nein, sie werden durch Werte gefüllt, die ich aus einem TableModel auslese:

```
Collection tCollection = (Collection)tTableModel.getValueAt(i,1);
```
Der Inhalt der Table wird zeilenweise in die Collection geschrieben


----------



## Murray (17. Dez 2007)

Mit diesem Statement wird die Collection zugewiesen; wie sie gefüllt wird, kann man hier nicht sehen.

Hast Du vieleicht irgendwo eine Catch-Block, in dem die gefangenen Exceptions einfach ignoriert werden? Möglicherweise tritt zur Laufzeit ein Cast-Fehler auf.


----------



## maki (17. Dez 2007)

Stefan79 sollte endlich man den verlangten Code posten, kann ja nicht so schwer sein...


----------



## Stefan79 (17. Dez 2007)

Das ist der Code, die Collection wird weiter nicht genutzt nur diese Zuweisung, dann das Speichern in der Map und wieder aus der Map heraus holen. Ansonsten wird nicht weiter auf die Collection zugegriffen.


----------



## maki (17. Dez 2007)

Nochmal langsam: Poste den Code, in dem deine Collections befüllt werden.

So verständlicher?


----------



## Murray (17. Dez 2007)

Versuch es mal so:


```
if ( tColl1.containsAll(tColl2)) {
        System.out.println( "containsAll -> true");
        tueEtwas();
    } else {
        System.out.println( "containsAll -> false");
    }
```


Kommt denn dann die zweite Ausgabe?


Und das 

```
Collection tColl1 = (Collection)tMap.get(tKeyList.get(i));
   Collection tColl2 = (Collection) tMap.get(tKeyList.get(i));
```
ist doch Unfug, oder? Wenn tKeyList nicht eine selbstimplementierte Klasse mit einem finsteren Seiteneffekt in der get-Methode ist, dann liefert tKeyList.get(i) doch in beiden Fällen den gleichen Key. Und die Map sollte dann doch auch in beiden Fällen das gleiche Objekt liefert, so dass tColl1 = tCol2 ist.


----------



## Stefan79 (17. Dez 2007)

Also, dies ist der gesamte Code in dem diese Collection genutzt wird. Weiter passiert damit nichts:

```
for(int i = 0; i < iTableModel.getRowCount();i++)
	      {
          String tKey = (String)iTableModel.getValueAt(i,0);
         
	        Collection tCollection = (Collection) iFunctionTableModel.getValueAt(i,1);
	        if(tColl.isEmpty())
	        {
	          return;
	        }
	        else 
	        {
            tStoreMap.put(tKey, tCollection);
	        } 
	      }
      List tKeyList = new ArrayList();       
   for(int i = 0; i < iKeyModel.getRowCount();i++)
   {
        tKeyList = iKeyModel.getValueAt(i,0);
    }

          Collection tColl1 = tStoreMap.get(tKeyList(0);
          Collection tColl2 = tStoreMap.getKeyList(1);
          if (tColl1.containsAll(tColl2))
          {
               MessagePane.show(this, Zwei identische Tabelleneinträge sind nicht zulässig");
           }
```

Mehr wird wirklich nicht gemacht


----------



## Murray (17. Dez 2007)

Diesen Code


```
List tKeyList = new ArrayList();       
   for(int i = 0; i < iKeyModel.getRowCount();i++)
   {
        tKeyList = iKeyModel.getValueAt(i,0);
    }
```
könnte man ersetzen durch 

```
List tKeyList  iKeyModel.getValueAt(iKeyModel.getRowCount()-1,0);
```
denn in der Schleife wird ja lediglich tKeyList immer neu zugewiesen.

Ist das wirklich so gewollt?


Und hier

```
Collection tColl1 = tStoreMap.get(tKeyList(0);
         Collection tColl2 = tStoreMap.getKeyList(1);
```
passt ja nichtmal von Anzahl der Klammern.


----------



## Stefan79 (17. Dez 2007)

Sorry, ein Tippfehler in der Eile.
Habe das ganze nun so gemacht, aber weiß halt nicht ob das wirklich so toll ist oder ob es zu Problemen kommen könnte:

```
if ( (tCompareColl != null) && (tComparatorColl != null) &&	      				                                                                           String.valueOf(tComparatorColl)).equalsIgnoreCase(String.valueOf(tCompareColl))))
{
     tueEtwas();
}
```

So würde es theoretisch funktionieren


----------



## Stefan79 (17. Dez 2007)

Sorry, ein Tippfehler in der Eile.
Habe das ganze nun so gemacht, aber weiß halt nicht ob das wirklich so toll ist oder ob es zu Problemen kommen könnte:

```
if (String.valueOf(tColl1).equalsIgnoreCase(String.valueOf(tColl2))
{
    tueEtwas();
}
So würde es theoretisch funktionieren
```


----------



## Murray (17. Dez 2007)

Sind tCompareCol und tComparatorCol jetzt die Collections? Dann ist das ziemlich schlecht - du verlässt dich hier darauf, dass die String-Repräsentationen der Collections genau dann gleich sind, wenn sie den gleichen Inhalt haben. Und davon kann man wohl i.d.R. nicht ausgehen.


----------



## Stefan79 (18. Dez 2007)

Naja, mir kommt es aber rein auf den Inhalt an, wenn der Inhalt gleich ist, dann soll eine Meldung an den Benutzer kommen. Es kommt nicht darauf an, ob beide Collections identisch sind, sondern ich möchte nur wissen, ob ihr Inhalt gleich ist. Könnte man es dann so machen mit String.valueOf() ??


----------



## Murray (18. Dez 2007)

Ob das funktioniert, hängt von der konkreten Implementierung der Collection sowie von den Inhalten der Collection ab. String#valueOf macht ja (sofern man ein Object als Parameter übergibt) nicht anders, als an diesem Object die Methode toString aufzurufen. Wenn die Collection jetzt z.B. eine ArrayList ist, dann erhält man einen String-Repräsentation, die wiederum aus den String-Repräsentationen der Elemente besteht, und zwar in der Reihenfolge, in der sie eingefügt wurden. Wenn jetzt noch sichergestellt ist, dass in der Liste solche objekte gespeichert sind, bei denen gilt, das zwei in deinem Sinne "gleiche" Objekte auch beim toString() den gleichen String liefern, dann wird es funktionieren.


----------



## Stefan79 (18. Dez 2007)

mhh.....scheint ja doch sehr unsicher zu sein. Aber wie könnte ich denn dann den Inhalt zweier Collections oder auch Listen miteinander vergleichen. Wie gesagt ich will nur wissen, ob der Inhalt gleich ist der Rest kann ruhig unterschiedlich sein. Also wenn in Collection 1 "Hallo" drin steht und in Collection 2 auch "Hallo", dann sollte ich true zurück bekommen.


----------



## Murray (18. Dez 2007)

Wenn du zwei Listen vergleichen willst, musst du sie elementweise vergleichen.


```
public boolean lstEqual( List lst1, Liste lst2) {

  if ( lst1 == null) return (lst2 == null);
  if ( lst2 == null) return false;

  int l1 = lst1.size();
  int l2 = lst2.size();
  if ( l1 != l2) return false;

  for ( int i=0; i<l1; i++) {
     Object o1 = lst1.get( i);
     Object o2 = lst2.get( i);
     if ( !o1.equals( o2)) return false;
  }

  return true;
}
```

Das liefert dann true, wenn alle Elemente übereinstimmen.


----------

