# Equals bei ArrayListen



## b1zarRe (7. Sep 2012)

Hi,

ich habe eine Klasse Student, welche nur aus long matrikelnummer und String name besteht.
Wenn ich nun die Equals() sowie die hashCode() Methode entsprechend überschreibe,
dann wird mir in zwei ArrayListen al1 und al2 equals true ausgeben, wenn ich vorher
diesen Code geschrieben habe:


```
Student s1 = new Student(123123,"Muster");
Student s2 = new Student(123123,"Muster");
ArrayList al1 = new ArrayList();
ArrayList al2 = new ArrayList();
al1.add(s1);
al2.add(s2);
System.out.println(al1.equals(al2));
```

Dies ist auch vollkommen verständlich, weil die ArrayListen den gleichen(->equals,hashcode)
Inhalt in der gleichen Reihenfolge enthalten.

Nun habe ich aber die Aufgabe herauszufinden, ob es möglich ist,
falls equals und hashcode nicht überschrieben, auch true herauskommen könnte. Und falls ja,
wie?

Ich habe nun versucht einfach das equals() und hashCode() auszukommentieren, aber da kommt false heraus(Was meinen Verständnis nach auch total korrekt ist, aber der Aufgabe ja nicht entgegen kommt).

Meine Frage ist also, ob es in irgendeiner Form möglich ist, equals() und hashCode() nicht 
zu überschreiben und dennoch in zwei Listen ein equals()->true herauszubekommen?
Diese würde meiner Meinung nach nur bei den elementaren Typen gehen(weil diese in Wrapper verpackt werden und dort equals überschrieben ist) oder zb.: mit Strings(weil dort auch die beiden
Methoden überschrieben sind). 

Geht das denn in irgend einem Fall auch für "eigene" Klassen???



EDIT:
ich glaube ich habe die Lösung schon gefunden, nämlich:


```
Student s1 = new Student(123123,"Muster");
ArrayList al1 = new ArrayList();
ArrayList al2 = new ArrayList();
al1.add(s1);
al2.add(s1);
System.out.println(al1.equals(al2)); //true
```

Dies ist true, obwohl Student equals() und hashcode() auskommentiert hat, weil
s1 ind beiden Arraylisten steckt UND da die equals() Methode nicht überschrieben, wird
diese von Object genommen, welche prüft ob es das SELBE(nicht gleiche!) Objekt ist,
und das ist true.

Gut, kann es noch einen anderen Fall geben?
Und warum zeigt dann s1 sowie s2, 


```
Student s1 = new Student(123123,"Muster");
Student s2 = new Student(123123,"Muster");
```
Nicht direkt auf das selbe Objekt? Warum wird quasi zweimal das gleiche Objekt im
Heap erzeugt und nicht wie zb.: bei Strings darauf geachtet, dass beide gleich sind
und nur eines?


----------



## SlaterB (7. Sep 2012)

> Gut, kann es noch einen anderen Fall geben?

falls leere Liste und Listen mit null-Elementen nicht zählen, nein

> Warum wird quasi zweimal das gleiche Objekt im
> Heap erzeugt und nicht wie zb.: bei Strings darauf geachtet, dass beide gleich sind
> und nur eines? 

bei String wird auch nicht immer darauf geachtet, nur bei direkt im Quellcode erstellten Konstanten,
evtl. auch Zusammenfügen von Konstanten

aber schon

```
public class Test {
    public static void main(String[] args)  {
        String testString = "a b c d e f g";
        String a = testString.substring(0, 2);
        String b = testString.substring(0, 2);
        System.out.println(a == b);
    }
}
```
liefert zwei unterschiedliche Strings a und b gleichen Inhalts

warum?
zum einen wäre es ein gewisser Aufwand, ein neues Objekt mit allen Strings/ Objekten eines Programmes zu vergleichen,
je simpler desto länger dauerts, je schneller desto aufwendigere Index-Strukturen würden benötigt, etwa HashMaps,
man selber kann das im Bedarfsfall machen, aber da 9.999 von 10.000 Fälle das nicht brauchen wäre das unnötiger Aufwand fest eingebaut

zum anderen will man das oft bis nahezu immer gar nicht, 
zwei Objekte mögen gleich beginnen, etwa leere Lottoscheine oder hier passend die zwei leeren ArrayListen, 
aber man will sie dann ja unterschiedlich befüllen,
soll irgendwann von alleine auf verschiedene Objekte gewechselt werden?

wenn es schon eine leere Liste gibt, eine mit "a", eine mit "a" und "b",
dann wird eine 4. neu erstellt, erst "a", dann "b", dann "c" eingefügt, wird dann durch die vorhandenen Objekte gesprungen?

manches davon ist sogar wieder denkbar in Eigenprogrammierung, für eine Programmiersprache an sich aber kein sinnvolles Verhalten


----------



## Firephoenix (7. Sep 2012)

b1zarRe hat gesagt.:


> Gut, kann es noch einen anderen Fall geben?
> Und warum zeigt dann s1 sowie s2,
> 
> 
> ...



Wenn du 2 mal einen blauen BMW herstellst, dann könntest du doch auch einfach einen herstellen und den von links und rechts anschauen - aber was machst du wenn du einen verkaufen und einen ausstellen willst?

Zu dem anderen Fall:
Was mit dazu einfällt ware der Java String-Pool Questions about Java's String pool - Stack Overflow
damit lässt sich sowas bauen:

```
public static void main(String[] args) {
		List<String> l1 = new ArrayList<String>();
		List<String> l2 = new ArrayList<String>();
		String s1 = "blauer BMW";
		String s2 = "blauer BMW";
		
		l1.add(s1);
		l2.add(s2);
		System.out.println(l1.equals(l2));
		System.out.println(s1 == s2);
	}
```

Ausgabe:


> true
> true



Gruß

Edit: zu langsam


----------



## b1zarRe (8. Sep 2012)

Noch eine Frage hinterher:


```
ArrayList al1 = new ArrayList();
al1.add("a");
al1 = new ArrayList();

System.out.println(al1.equals(new ArrayList()));
```

Ausgabe "false".... aber warum genau?
Mir ist klar, wenn ich in Zeile 3 geschrieben hätte al1.clear(); würde
als Ausgabe true herauskommen. ABER al1=new ArrayList(); bedeutet
doch soviel wie al1 zeige auf eine NEUE(leere) Arraylist. Oder referenziert
al1 nun quasi zwei Listen? Einmal die mit dem "a" und einmal eine ganz neue
leere?!


----------



## SlaterB (9. Sep 2012)

bei mir ist die Ausgabe "true"..


----------



## b1zarRe (9. Sep 2012)

ich meinte es natürlich so(sorry):


```
HashMap hm = new HashMap();
ArrayList al1 = new ArrayList();

al1.add("a");
hm.put("B", al1);
al1 = new ArrayList();

System.out.println(hm.get("B").equals(new ArrayList()));
```

Ausgabe ist hier nun 'false'.... liegt das daran, dass eine
mit Inhalt gefüllte ArrayList bereits der Hashmap übergeben worden
ist und die Anweisung von al1=newArrayList(); die HashMap 
garnicht mehr betrifft, oder wie ist das zu erklären?


----------



## Gast2 (9. Sep 2012)

Jo, du überschreibst den Inhalt der Variablen al1, das ändert aber am Inhalt der HashMap nichts.


----------



## b1zarRe (9. Sep 2012)

Okay, also kann ich den Schluss daraus ziehen,
dass wenn ich etwas in einer HashMap zuordne jede
weitere Veränderung der Zuordnung keinen Effekt
auf die HashMap hat ausser ich würde die 
HashMap selbst verändern(wie zb.: einen Key löschen) ?


----------



## SlaterB (9. Sep 2012)

HashMap musst du nicht groß bemühen,

bei einfachen Variablen ist das genauso:
> ArrayList a = ..;
> ArrayList b = a;
> a = ..;

Variable b zeigt auf das erste Objekt, auf welches zuvor a gezeigt hat,
wenn dann die Variable a auf ein zweites Objekt umgestellt wird, ist das erste davon nicht betroffen,
evtl. zeigen tausende andere Variablen darauf oder nur b

wenn aber a kein neues Objekt zugewiesen sondern das erste Objekt verwendet wird, etwa ein weiteres Element in die Liste eingefügt,
dann ist das für b auch relevant bzw. z.B. für die HashMap, denn die zeigen ja auf dasselbe Objekt, es kann durchaus verändert werden, das kann auch ganz schön Probleme etwa in der Sortierung machen

Objektveränderung vs Zuweisung neuer Objekte muss man auseinanderhalten,
Strings sind unveränderlich, aber Stringvariablen kann man auch neue Strings zuweisen


----------



## b1zarRe (13. Sep 2012)

Mir ist heute noch folgendes aufgefallen:


```
ArrayList<Object> eineListe;
        int laenge;
        Object obj;

        liste = new ArrayList<Object>(10);

        liste.add("zweites Element");
        liste.add(0, "erstes Element");
        liste.add(new Integer(100));
        obj = liste.set(2, new Double(5.0)); //!!!
        laenge = liste.size();

        System.out.println(liste); //Ausgabe: erstes Element, zweites Element, 5.0 --> Okay!
        System.out.println(laenge); //Ausgabe: 3 --> Okay
        System.out.println(obj); // Ausgabe: 100 ---> was zum henker....?!
```

Warum kommt bei der letzten Ausgabe 100 heraus? Etwa weil obj auf das Element zeigt, was
in der Liste an 2. Stelle ist(bis dahin 100), dieses verändert aber immernoch auf das alte zeigt?!


----------



## SlaterB (13. Sep 2012)

was gibt es da zu rätseln? in der API zu set() steht doch ganz genau was zurückgegeben wird,
nämlich das Integer(100)-Objekt,
was meinst du mit "verändert aber immernoch auf das alte zeigt?! "?

set() gibt jedenfalls nicht ein ominöses Gebilde zurück, welches das Element der Liste an Index 2 beschreibt und deren Zustände in Raum und Zeit merkt und als ausführlichen Bericht wiedergibt

LinkedList hat mit Entry in etwa derartiges, 
eine ArrayList ist aber nur ein Array, eine int-Variablen und je nach Zuzählung die referenzierten Objekte


----------



## b1zarRe (13. Sep 2012)

Okay,
das war meine Dummheit oder zuviel geproggt... Klar der RÜckgabetyp ist einfach in dem Fall die 100....., ich Idiot. -.-
Habe sonst nur set benutzt um was zu verändern, aber nie ausgegeben und gesehen, dass da auch der alte Wert zurückgegben wird... my mistake, excuse me


----------

