# Aufgabe zur Verwaltung von Objekten



## JavaIsTheBest (2. Mrz 2016)

Hallo,
diese Aufgabe ist gegeben. Der Quellcode war schon gegeben. Das einzige, was ich implementiert habe sind die Methoden public boolean equals(Object other), public int hashCode() und public String toString().
Mein Problem: Der Compiler zeigt mir einen Fehler an, weil ObjectSet in der Methode equals keine Variable ist.
Könntet ihr mir auch Tipps zu der Methode toString geben?



Spoiler: Klasse ObjectSet





```
public class ObjectSet {
    // Menge von Strings.
    // Array von Elementen.
    private String[] elems;
    // Tatsächliche Anzahl der Elemente.
    // Arraypositionen mit Index >= card sind unbenutzt.
    private int card;

    // Position von s im Array elems liefern, falls es enthalten ist.
    // Andernfalls -1 liefern.
    private int search(String s) {
        for (int i = 0; i < card; i++) {
            if (elems[i].equals(s))
                return i;
        }
        return -1;
    }

    // Leere Menge mit Kapazität n >= 0 (d. h. Platz für n Elemente) erzeugen.
    public ObjectSet(int n) {
        elems = new String[n];
        card = 0;
    }

    // Leere Menge mit Kapazität n >= 0 erzeugen und anschließend
    // Element s einfügen, falls dies möglich ist (vgl. insert).
    public ObjectSet(int n, String s) {
        this(n);
        insert(s);
    }

    // Kapazität der Menge (d. h. Wert des Konstruktorparameters n) liefern.
    public int capacity() {
        return elems.length;
    }

    // Kardinalität der Menge (d. h. tatsächliche Anzahl ihrer Elemente)
    // liefern.
    public int card() {
        return card;
    }

    // Menge in der Form "{ }", "{ a }", "{ a, b }" etc. ausgeben.
    public void print() {
        System.out.print("{");
        String comma = " ";
        for (int i = 0; i < card; i++) {
            System.out.print(comma + elems[i]);
            comma = ", ";
        }
        System.out.print(" }");
    }

    // Enthält die Menge das Element s?
    public boolean contains(String s) {
        return search(s) >= 0;
    }

    // Element s einfügen und true liefern, falls es noch nicht enthalten
    // und nicht null ist und die Kapazität der Menge noch nicht erschöpft ist;
    // andernfalls false liefern.
    public boolean insert(String s) {
        // Wenn das Element s null ist, soll es nicht eingefügt werden.
        if (s == null)
            return false;
        // Wenn die Kapazität erschöpft ist,
        // kann das Element nicht eingefügt werden,
        // egal, ob es bereits enthalten ist oder nicht.
        // Da diese Überprüfung schneller geht als die nächste,
        // wird sie zuerst durchgeführt.
        if (elems.length == card)
            return false;
        // Wenn das Element s bereits enthalten ist,
        // soll es nicht nochmals eingefügt werden.
        if (search(s) >= 0)
            return false;
        // Element an Position card speichern und Kardinalität erhöhen.
        elems[card++] = s;
        return true;
    }

    // Element s entfernen und true liefern, falls es enthalten ist;
    // andernfalls false liefern.
    public boolean remove(String s) {
        // Ein null-Element ist niemals in der Menge enthalten.
        if (s == null)
            return false;
        // Nach dem Element s suchen.
        int i = search(s);
        // Wenn das Element s nicht enthalten ist, ist nichts zu tun.
        if (i == -1)
            return false;
        // Letztes Element an Position i verschieben
        // und Kardinalität erniedrigen.
        elems[i] = elems[--card];
        elems[card] = null;
        return true;
    }

    // Schnittmenge der Mengen first und second als neue Menge mit
    // geeigneter Kapazität liefern (first und second bleiben unverändert).
    public static ObjectSet intersection(ObjectSet first, ObjectSet second) {
        // Leere Resultatmenge erzeugen.
        // Sie besitzt höchstens so viele Elemente
        // wie die kleinere der beiden Mengen.
        int n = first.card < second.card ? first.card : second.card;
        ObjectSet result = new ObjectSet(n);
        // Alle Elemente der Menge first, die auch in der Menge
        // second enthalten sind, zur Resultatmenge hinzufügen.
        for (int i = 0; i < first.card; i++) {
            String s = first.elems[i];
            if (second.contains(s))
                result.insert(s);
        }
        return result;
    }
    public boolean equals(Object other){
        if(other instanceof ObjectSet && other.equals(ObjectSet)){
            return true;
        }
        return false;
    }
    public int hashCode(){
        int summe=0;
        if(card==0) return summe;
        for(int i=0;i<card;i++){
            summe+=elems[i].hashCode();
        }
        return summe;
    }
    public String toString(){
        return "";
    }

}
```


----------



## Jardcore (2. Mrz 2016)

Ersteinmal hast du innerhalb deiner equals Methode den Aufruf other.equals(ObjectSet) benutzt.
Du versuchst hier quasi den Bauplan in die equals() zu schieben, dort musst du jedoch mit "this" arbeiten.


```
public boolean equals(Object other){
        ObjectSet objectSet = null;
        if(other instanceof ObjectSet) {
            objectSet = (ObjectSet) other;
            return other.equals(this);
        }
        return false;
    }
```
}

In der Aufgabenstellung steht jedoch das du noch die Elemente prüfen sollst, das solltest du vielleicht noch hinzufügen. Deshalb musst du wahrscheinlich das Object noch in dein explizites Objekt casten. Und dann die extra Prüfung durchführen.

Sonst sähe deine equals() Methode nämlich nur so aus

```
public boolean equals(Object other) {
    return other instanceof ObjectSet && other.equals(this);
}
```
Das wäre aber richtig bescheuert^^ weil der erste equals() Aufruf schon guckt ob beide gleich sind. Den zweiten könnte man sich also sparen.

EDIT: wie ich sehe musst du die Klasse noch weiter bearbeiten. Denn sie soll nun beliebige Objekte speichern können. Und bisher gehen nur Strings.


----------



## JavaIsTheBest (2. Mrz 2016)

1. Warum sollte ich "this" benutzen? Was bedeutet dieses this? Ist damit einfach ein Objekt vom Typ ObjectSet gemeint?
2. Auf was soll ich diese Elemente überprüfen?
3.

```
public boolean equals(Object other) {
    return other instanceof ObjectSet && other.equals(this);
}
```
Es wird doch zuerst überprüft ob other ein Objekt vom Typ ObjectSet ist. Das ist noch keine Überprüfung ob, die beiden gleich sind.
4.


> EDIT: wie ich sehe musst du die Klasse noch weiter bearbeiten. Denn sie soll nun beliebige Objekte speichern können. Und bisher gehen nur Strings.



Das heißt aus String ein Object machen?


Da ich vorhin in Eile war, konnte ich nicht die vollständige Aufgabenbeschreibung posten.


----------



## Blender3D (3. Mrz 2016)

Ja aus String einem speziellem Objekt mache ein allgemeines Objekt.
Du sollst in dem Set ja beliebige Objekte speichern.
Die Funktion equals soll ja auf Gleichheit des Inhaltes der beiden Objekte testen.
Das bedeutet, dass beide Seiten die gleiche Anzahl an Objekten beinhaltet. Da es sich um ein Set also eine Menge handelt -> {a,c,d} = {d,a,c} also kannst du nicht einfach die einzelnen Objekte in einer Schleife miteinander vergleichen. Dafür benutzt du HashCode um eine Gleichheit zu ermitteln.

```
public boolean equals(Object other) {
        if (!(other instanceof ObjectSet)) {
            return false;
        }
        ObjectSet test = (ObjectSet) other;
        if (test.elems.length != elems.length)
            return false;
        return hashCode() == other.hashCode();
    }
```


----------



## JavaIsTheBest (3. Mrz 2016)

Der hashcode sagt mir sehr wenig. Könntest du mir das wichtigste zum hashcode erklären?


----------



## Blender3D (3. Mrz 2016)

```
public boolean equals(Object other) {
        if (!(other instanceof ObjectSet)) {
            return false;
        }
        ObjectSet test = (ObjectSet) other;
        if (test.elems.length != elems.length)
            return false;
        for( int i = 0; i< elems.length; i++ ){
            if( !elems[i].equals(test.elems[i]) )
                return false;
        }
        return true;
    }
```
Das ist die Variante, wenn alle Element an der selben Stelle liegen.


----------



## Blender3D (3. Mrz 2016)

Also der HashCode ist eigentlich keine Gute Lösung, da man nicht sicher sein kann, dass die Sets auch wirklich gleich sind. Es ist eine Art Signatur, die aber auf mehrere Objekte zutreffen kann.
Er wird verwendet, um z.B. den Zugriff auf Elemente zu beschleunigen. Er bildet eine große Menge auf eine kleinere Zielmenge ab.


----------



## Blender3D (3. Mrz 2016)

Die wahrscheinlich richtige Lösung für Dich ist diese.

```
public boolean equals(Object other) {
        if (!(other instanceof ObjectSet)) {
            return false;
        }
        ObjectSet test = (ObjectSet) other;
        if (test.elems.length != elems.length)
            return false;
        for (int i = 0; i < elems.length; i++) {
            if (test.search(elems[i]) < 0)
                return false;
        }
        return true;
    }
```


----------



## Blender3D (3. Mrz 2016)

1) Prüfen ob other vom Type Objectset ist.
2) Wenn ja caste auf diesen Typ, um dessen Funktionalität zu erhalten.
3) Vergleiche die Anzahl der Elemente beider Sets.
4) Bei Gleichheit suche alle Elemente des 1ten Sets im 2ten Set.
Ist das alles erfolgreich, dann sind die Sets gleich.


----------



## Jardcore (3. Mrz 2016)

Um nochmal *this *zu klären.
Deine Klasse ist sozusagen dein Bauplan. Mit diesem Bauplan kannst du sogenannte Objekte oder Instanzen anlegen. (Stichwort: *new *).

Hier ein kleines Beispiel:

```
// Ein ObjectSet wird angelegt und anhand der Variable "set" referenziert.
// Das heißt du kannst auf die Adresse des Objects im Speicher mithilfe der Variable "set" zugreifen.
ObjectSet set = new ObjectSet();
```
Wenn du jetzt innerhalb des Objects aus einer Methode herraus eine Referenz auf dein Object haben willst benutzt du "this"... this ist so wie oben die Reference zu deinem erstellten ObjectSet.
Gut zu sehen ist das immer im Konstruktor 

```
public class ObjectSet {
    private int zahl;
    // konstruktor
    public ObjectSet(int zahl) {
        this.zahl = zahl;
    }
}
```


----------



## JavaIsTheBest (3. Mrz 2016)

> Wenn du jetzt innerhalb des Objects aus einer Methode herraus eine Referenz auf dein Object haben willst benutzt du "this"... this ist so wie oben die Reference zu deinem erstellten ObjectSet.
> Gut zu sehen ist das immer im Konstruktor



Wie kann ich mir eine Referenz auf ein Objekt vorstellen? Bzw. was ist eine Referenz auf ein Objekt?


----------



## Blender3D (4. Mrz 2016)

Deine Objekte befinden sich ja irgendwo im Speicher Deines Computers. *Die Referenz ist ein konstanter Zeiger auf den Speicherort des Objekts*. Beim erstellen des Objekts mit z.B.
ObjectSet set = new ObjectSet(10); Wird der Variables set diese Referenz zugewiesen. Das ermöglicht den Zugriff auf dieses Objekt.
In anderen Programmiersprachen wie z.B. C oder C++ gibt es außerdem noch Zeiger die nicht konstant sind. Das heißt man kann deren Zieladresse verändern. Das eröffnet einerseits neu Möglichkeiten für den Programmierer, stellt diesem aber auch neu Fallstricke wie z.B. fehlerhafte Speicherzugriff oder Speicherlöcher die entstehen.


----------



## JStein52 (5. Mrz 2016)

Blender3D hat gesagt.:


> *Die Referenz ist ein konstanter Zeiger auf den Speicherort des Objekts*


Das eigentliche Thema ist ja wohl durch. Aber da ist schon ein kleiner Fehler. Wieso sollte das ein konstanter Zeiger sein ?  Du kannst doch auch so was machen:


```
ObjectSet set = new ObjectSet(10);
          set = new ObejctSet(13);
```
Dann referenziert set zunächst den ersten ObjectSet und gleich drauf den anderen. (der erste fällt der GC anheim) ...  oder meintest du was anderes ?


----------



## thecain (5. Mrz 2016)

In C kannst du z.b. sowas machen


```
int  var[]={10,100,200};
int *ptr;

/* let us have array address in pointer */
ptr =var;
printf("%d", *ptr );  //10
ptr++;
printf("%d", *ptr ); //100
```

das geht in Java nicht. Ich vermute mal er meint das


----------



## Blender3D (6. Mrz 2016)

JStein52 hat gesagt.:


> ObjectSet set = new ObjectSet(10);
> set = new ObejctSet(13);


Hier weist Du der Variable set nur eine neue Referenz zu. Du veränderst nicht den Inhalt der konstenten Zeigers ( Referenz) .


----------



## Blender3D (6. Mrz 2016)




----------

