Dieser Code sagt mir nichts...

RezaScript

Bekanntes Mitglied
Hallo,

obwohl ich schon viel darüber gelesen habe, verstehe ich diese Zeile immer noch nicht:

Java:
static Set<Session> users = Collections.synchronizedSet(new HashSet<Session>());

Ich weiss, dass es eine Variable ist und dieser "Sammlung" können Daten mit users.add("Hallo") hinzugefügt werden. Mehr weiss ich aber auch nicht.

Wäre sehr dankbar, wenn mir jemand den Code Stück für Stück erklären würde.
 
Ein Set ist eine ungeordnete Menge von Objekten, in der jedes Objekt nur einmal vorkommen kann (analog einer mathematischen Menge). HashSet ist eine konkrete Set-Implementierung. Collections.synchronizedSet liefert für ein gegebenes Set ein Set, dessen Zugriffe synchronisiert sind, so dass aus mehreren Threads parallel darauf zugegriffen werden kann.
 
Okay danke aber das sind mir etwas zu viel Informationen und jetzt bin ich noch verwirrter als vorhin 🙂

Ich muss vielleicht etwas zurückspulen. Fangen wir mal mit static an.

static
Soweit ich weiss, wird es aus Memory-Gründen verwendet. Wenn also 1 Objekt den Wert der Static-Variable verändert, ändert sich der Wert auch bei alle anderen Objekten. Wenn static bei einer Methode eingesetzt wird, muss die Klasse der Methode nicht vorerst instanziiert werden, sondern kann direkt via z.B. Klasse.methode() aufgerufen werden. Korrigiere mich bitte wenn ich falsch liege.

Set<Session>
Ich gehe davon aus, dass es sich dabei um den Datentyp der Rückgabewert der Klasse Set handelt. Also genau wie wenn ich String text = "Hallo"; eingeben würde. Was danach aber mit <Session> gemeint ist, weiss ich nicht.

users
Das ist klar. So heisst die Variable.

Collections
Das ist eine Klasse, die mir statische Methoden wie synchronizedSet() zur Verfügung stellt.

synchronizedSet()
Den Set gebe ich als Parameter mit. Die Methode synchronisiert mir den Set, wieso auch immer und was auch immer mit "synchronisieren" gemeint ist. Da verstehe ich nur Bahnhof.

new HashSet<Session>()
Als Parameter wird hier ein HashSet definiert, welche nur Sessions beinhalten sollte (aber rein theoretisch könnte ich hier auch ArrayList() verwenden).

Via HashSet<String> users = new HashSet<String>(); (wieso auch immer ich hier zweimal <String> eingeben muss) könnte ich name.add("Peter"); verwenden, um Daten in der "Kette" einzufügen. Ich gehe davon aus, dass add() eine Methode der Klasse HashSet ist. Bei static Set<Session> users = Collections.synchronizedSet(new HashSet<Session>()); könnte ich jedoch auch users.add("Peter") verwenden. Warum kann ich hierbei die Methode add() verwenden? Die Klasse Collections hat ja keine add()-Methode. Zumindest konnte ich sie hier nicht finden: https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html

Was genau ist überhaupt der Unterschied zwischen
Java:
static Set<Session> users = Collections.synchronizedSet(new HashSet<Session>());
und
Java:
List test = new ArrayList();
abgesehen davon, dass bei ArrayList() mehrere Objekte vorkommen können?
 
static: kann man so stehen lassen.

Was danach aber mit <Session> gemeint ist, weiss ich nicht.
Das Session ist ein Typparameter (s. a. Generics), der der Typsicherheit dient. Wird kein Typparameter verwendet, wird automatisch Object angenommen.

Bei einem Set ohne Typparameter hättest Du eine Menge von beliebigen Objekten, Du könntest z. B. Zahlen und Strings hineinstecken, beim Rausholen müsstest Du aber immer prüfen, von welchem Typ das jeweilige Objekt ist, da die Menge den genauen Typ der Objekte ja nicht kennt. Selbst, wenn Du nur Strings reinsteckst, gibt Dir ein solches Set nur ein Object zurück, so dass Du dem Compiler mit einem "type cast" explizit der Typ mitteilen müsstest.

Zum Beispiel (ohne Typparameter):
Java:
public void summe(Set menge) {
    int sum = 0;
    for (Object obj : menge) { // die menge kennt keinen Typ, also wird vom allgemeinsten ausgegangen: Object
        if (obj instanceof Integer) { // prüfen, ob das Objekt vom Typ Integer ist, man weiß ja nie...
            sum += (Integer)obj;     // cast von Object auf Integer
        }
    }
    System.out.println("Summe: " + sum);
}

Jetzt mit Typparameter:
Java:
public void summe(Set<Integer> menge) { // Menge von Integer-Objekten
    int sum = 0;
    for (Integer wert : menge) {  // jetzt ist klar, dass die Elemente vom Typ Integer sind
        sum += wert;
    }
    System.out.println("Summe: " + sum);
}

Collections: genau, eine Utility-Klasse

Die Methode synchronisiert mir den Set, wieso auch immer und was auch immer mit "synchronisieren" gemeint ist. Da verstehe ich nur Bahnhof.
Es geht darum, dass ein und dieselbe Ressource (hier: das Set) von ggf. mehreren Threads parallel verwendet wird. Wenn zwei Kunden im Supermarkt ihr Obst wiegen, verwenden sie ein und dieselbe Ressource (die Waage). Es wäre nun äußerst ungünstig, wenn beide gleichzeitig ihre Bananen auf die Waage legen und auf den Bananenknopf drücken. Das Gewicht stimmt nicht, dann kommt ggf. nur ein Zettel raus usw. Daher muss der Zugriff auf die Waage synchronisiert werden: der eine wartet, bis der andere fertig und die Waage wieder frei ist.

Genau das gleiche muss hier auch berücksichtigen: Du hast mehrere Websockets, die alle das selbe Set verwenden wollen. Das funktioniert nur stabil, wenn der Zugriff auf das Set synchronisiert wird.

Als Parameter wird hier ein HashSet definiert, welche nur Sessions beinhalten sollte (aber rein theoretisch könnte ich hier auch ArrayList() verwenden).
Na, dann kennst Du Dich ja mit dem Typparametern aus 🙂 Eine ArrayList könntest Du theoretisch auch verwenden, dann müsstest Du aber Collections.synchronizedList für die synchronisierte Variante aufrufen (es gibt übrigens auch Collection-Klassen, die von Haus aus auf den parallelen Zugriff ausgelegt sind, aber ich will Dich jetzt nicht weiter verwirren).

wieso auch immer ich hier zweimal <String> eingeben muss
musst Du nicht: HashSet<String> users = new HashSet<>(); reicht.

Ich gehe davon aus, dass add() eine Methode der Klasse HashSet ist.
Genau genommen ist add eine Methode des Interface Set (s. https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) und HashSet implementiert dieses Interface und damit auch die Methode.

Bei static Set<Session> users = Collections.synchronizedSet(new HashSet<Session>()); könnte ich jedoch auch users.add("Peter") verwenden.
Nein. Die Variable users ist als Set für den Typ Session deklariert. Daher kannst Du nur Session-Objekte hinzufügen.

Die Klasse Collections hat ja keine add()-Methode. Zumindest konnte ich sie hier nicht finden:
Collections.synchronizedSet ist eine Methode, die ein Objekt mit Set-Interface (für den angegebenen Typ) zurückgibt. Dieses Set wird anschließend der Variablen users zugewiesen. users.add bezieht sich also nicht auf Collections sondern auf das von der Methode Collections.synchronizedSet zurückgegebene Set.

Was genau ist überhaupt der Unterschied zwischen
Ich weiß jetzt leider nicht, worauf Du hinaus willst.
 

Zurück
Oben