Wie mache ich die Variable xyz eindeutig/unique?

uppss

Aktives Mitglied
Hallo Jungs,

angenommen, ich habe eine einfache Klasse Person und dort einige Attribute wie:

Java:
public class Person {
    private String name;
    private String age;
}

Wie mache ich die Variable name eindeutig/unique?
 

uppss

Aktives Mitglied
unique

für die spätere Implementieruntg so etwa (schnell getippt):
Java:
public Person findPersonByName(String name) throws PersonException {
        Person p1 = new Person("a", 10); // a und b müssen eindeutig sein
        Person p2 = new Person("b", 11);
        Person p2 = new Person("b", 11); // sollte nicht gehen, oder soll ich zum Set greifen? Die Anforderung ist aber, dass name *eindeutig* sein muss :-)
       
        persons.add(p1);
        persons.add(p2);
   
        List<Person> persons = ArrayList<>();
   
        for (person : persons) {
            if (name.contains(name)) {
                return person
            } else {
                throw new PersonException();
            }
        }
    return null;
    }
 

Robert Zenz

Top Contributor
Das kommt darauf an was genau du willst, willst du das ein Fehler geworfen wird, oder willst du die selbe Instanz wieder haben? So oder so musst du dir ein globales/statisches Set halten mit allen bereits vergebenen Namen in dem du dann nachschaust ob dieser Name bereits verwendet wurden.

Aber eigentlich habe ich mehr das Gefuehl dass du vielleicht die Anforderung falsch verstanden hast, das macht schon relativ wenig Sinn. Fuer gewoehnlich wuerde man bei so etwas eher ueber eine Fabrikmethode gehen und dann immer eine bereits erzeugte Instanz zurueckliefern wenn es fuer diese Werte bereits eine gibt.
 

Neumi5694

Top Contributor
Du willst also, dass alle Personen einen eigenen Namen haben.
Speichere sie in einer Map ab: Map<String,Person>
Die Map bietet dir nun Möglichkeiten, zu prüfe, ob eine solche Person schon existiert (für das Werfen der Exception) oder auch praktische Methoden, Personen bei Bedarf neu anzulegen, z.B. putIfAbsent oder computeIfAbsent. Ich bevorzuge letztere, hier würde keine unnötige Person erzeugt, falls sie schon vorhanden ist. Außerdem wird immer der aktuelle Wert als Ergebnis geliefert, während putIfAbsent den vorher gespeicherten Wert liefert, also auch null.
 
Zuletzt bearbeitet:

temi

Top Contributor
unique

für die spätere Implementieruntg so etwa (schnell getippt):
Java:
        Person p1 = new Person("a", 10); // a und b müssen eindeutig sein
        Person p2 = new Person("b", 11);
        Person p2 = new Person("b", 11); // sollte nicht gehen, oder soll ich zum Set greifen? Die Anforderung ist aber, dass name *eindeutig* sein muss :-)
Willst du bereits verhindern, dass die "doppelte" Person erzeugt werden kann?

Wie @Robert Zenz schon geschrieben hat, ist das vermutlich nicht gemeint. Eher, dass eine Liste von Personen keine Personen mit gleichem Namen enthält. Dazu hat @Neumi5694 schon was geschrieben. Es gibt natürlich noch mehr Möglichkeiten, z. B.
Java:
class Persons {
    private Set<String> names = new HashSet<>();
    private List<Person> persons = new ArrayList<>();
   
    public boolean add(Person person) {
        // Prüfe vor dem Hinzufügen der Person, ob der Name bereits vorhanden ist
    }
   
    // ...
}

Du kannst auch direkt ein Set<Person> verwenden, sofern dir die Methoden, die Set anbietet ausreichen. Aufpassen: In dem Fall muss die Klasse Person sowohl equals() als auch hashCode() überschreiben!
 
Zuletzt bearbeitet:

temi

Top Contributor
Ein kleiner Hinweis (am Rande): Das funktioniert natürlich auch ohne das HashSet, indem du vor dem Hinzufügen prüfst, ob die Person schon in der Liste ist. Die HashSet.contains() Methode arbeitet allerdings in O(1), während für ArrayList.contains() O(n) gilt.

Im Gegenzug (für den Fall, dass du nur das Set verwenden würdest) sind die Zugriffsmethoden von Set (Iterator) eher langsam.

Die gezeigte Lösung kombiniert demnach das Beste aus Beiden, braucht dafür aber natürlich mehr Speicher.

Was "besser" ist, das hängt immer von den konkreten Anforderungen ab.

Falls ich mich in meiner Ausführung irre, dann bitte korrigieren.
 
Zuletzt bearbeitet:

uppss

Aktives Mitglied
vielen Dank, ich habe Person#equals überschrieben
Warum hashCode() überschreiben, habe ich noch nicht verstanden?
 

Neumi5694

Top Contributor
vielen Dank, ich habe Person#equals überschrieben
Warum hashCode() überschreiben, habe ich noch nicht verstanden?

Wenn du eine Hashmap oder ein Hashset verwendest, wird anhand des Hashcodes entschieden, in welchem Subcontainer gesucht werden muss.
equals und in hashCode sollten deshalb immer die gleichen Felder berücksichtigen.

Edit: Ich denke, das ist vor allem eine Frage der Geschwindigkeit. Da ein überschriebenes equals nicht nur auf "this" prüft, sondern auch weitere Felder durchgeht, büßt eine Map etwas an Geschwindigkeit ein. Mit einer groben Gruppierung anhand des Hashcodes macht wieder etwas wett.
Ich bin mir jetzt auch gar nicht mal mehr so sicher, ob wirklich alle Felder aus Equals in hashCode berücksichtigt sein sollten, das hab ich nur mal als Empfehlung gelesen
 
Zuletzt bearbeitet:

thecain

Top Contributor
Wichtig ist einfach:
Wenn equals true ergibt, müssen auch die HashCodes gleich sein. Deswegen macht es auch Sinn beim Überschreiben von equals, hashcode ebenfalls zu überschreiben.

Wenn equals ungleich ist, müssen die HashCodes nicht unterschielich sein. Theoretisch wäre also eine hashCode Methode die immer den selben Wert zurückgibt zulässig, wenn auch sehr sinnlos.
 

KonradN

Super-Moderator
Mitarbeiter
Warum hashCode() überschreiben
Da ist die Antwort einfach: Wenn Du on anderen Klassen ableitest, musst der "Vertrag" eingehalten werden. Jedes abgeleitete Objekt muss sich so verhalten, wie das, wovon abgeleitet wurde (Siehe dazu Liskovs Substitution Principle).
Und der Vertrag bei hashcode und equals findet sich in Object:

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
 

Neumi5694

Top Contributor
Der Vertrag wäre also auch mit einer konstanten Zahl erfüllt, wie thecain es oben beschrieben hat, was auch die default-Umsetzung ist (es sei denn, ich interpretiere einen der Punkte falsch)
 

Neumi5694

Top Contributor
Ein kleiner Hinweis (am Rande): Das funktioniert natürlich auch ohne das HashSet, indem du vor dem Hinzufügen prüfst, ob die Person schon in der Liste ist. Die HashSet.contains() Methode arbeitet allerdings in O(1), während für ArrayList.contains() O(n) gilt.
Bei Hash-Umsetzungen hängt das stark davon ab, wie der Hashcode implementiert ist. Überschreibt man ihn nicht und es kommt immer die selbe Zahl, so landet alles im selben Container und das Ganze ist ähnlich schnell/langsam wie eine Liste. Nur wenn bekannt ist, wo das Element sich befindet, ohne irgendwas durchiterieren zu müssen, sind wie bei O(1).

Hier hat mal jemand was zu den Set und Zugriffszeiten geschrieben.


ps: Falls sich jemand Gedanken wegen der Berechnungszeit des Codes macht: Mehrere Berechnungsschritte hintereinanderkönnen moderne Prozessoren viel effizienter verarbeiten als Schleifen. Je nach Pipeline-Länge kann das alles in einem Zyklus (nicht zu verwechseln mit der Taktgeschwindigkeit) passieren, während eine Schleife mit nur einem Befehl ebenfalls jedes Mal auf das Ende des vollen Zyklus warten muss, selbst wenn es nur ein einfacher Befehl war. Es kann natürlich sein, dass diese Info nicht mehr akkurat ist (dass z.B. das Ergebnis aus einer Pipeline schon vor dem Ende erhalten werden kann), hab mich seit Ewigkeiten nicht mehr damit beschäftigt (Damals war Vektorprogrammierung der ganz große Wurf, danach kräht heute kein Hahn mehr).
Bitte in dem Fall korrigieren.
 

KonradN

Super-Moderator
Mitarbeiter
was auch die default-Umsetzung ist (es sei denn, ich interpretiere einen der Punkte falsch)
Die default HashCode Methode gibt nicht einen konstanten Wert zurück. Was da beschrieben wurde ist, dass wenn auf einer konkreten Instanz mit einem Zustand mehrmals HashCode aufgerufen wird immer der gleiche Wert zurück gegeben wird.

Zwei unterschiedliche Instanzen oder wenn eine Instanz geändert wird, können unterschiedliche hashcode geben und die default Implementation gibt in der Regel für jede Instanz einen anderen Wert.
 

temi

Top Contributor
was auch die default-Umsetzung ist

Der Text in der Dokumentation zu hashCode() geht noch weiter:
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
 
Zuletzt bearbeitet:

Neumi5694

Top Contributor
Wenn ich mich jetzt nicht komplett täusche, ist der default hashcode oben nicht konstant
Wurde mir im Forum hier so gesagt, nachdem ich was anderes behauptet hatte :) Ich sollte halt nicht alles glauben.
Der Quelltext hierzu ist eh nicht ersichtlich, eine native Methode wird aufgerufen (womit wir beim C-Teil der JRE angekommen wären).
 

KonradN

Super-Moderator
Mitarbeiter
Also bezüglich equals / hashcode kenne ich nur einen Fall, wo man mit einem konstanten hashcode arbeiten könnte: Wenn man mit Entities z.B. mit Hibernate arbeitet, dann sollte man sich überlegen, wie man equals implementieren möchte.

Dazu gibt es dann z.B. folgenden Blog-Eintrag:

Die ganz kurze Zusammenfassung:
  • Wann sind zwei Elemente gleich? Hier wäre die Idee, dass zwei Elemente, die gespeichert wurden, gleich sind, wenn die Id gleich ist. Wenn die Id null ist von einem oder mehrere Elemente, dann sind diese ungleich.
  • Was nimmt man nun als hashcode? Da könnte man die id nutzen. Wenn die ID aber erst beim speichern erzeugt wird, dann könnte folgendes passieren;
1. Ein neues Element wird erzeugt. id ist null, hashcode ist dann halt, was man bei null id vorgesehen hat (z.B. 0)
2. Das neue Element nutze ich nun als key in einer HashMap.
3. Ich speichere das Element. Die id wird gesetzt, der Hashcode ist nun verändert.
4. Nun kann ich das Element nicht mehr in der Map finden, da der HashCode nun verändert ist.

==> Hier kann es also sinnvoll sein, einen fixen HashCode zu verwenden.

Ich nutze bei meinen Entities dennoch die Id als HashCode. Das setzt aber voraus, dass man eben eine Entity erst "speichert", ehe man diese in einer Struktur nutzt, die einen HashCode nutzt. Das ist eine Einschränkung, mit der ich sehr gut leben kann und die ich bisher nicht als Einschränkung empfunden habe.
 

sastahai44

Neues Mitglied
Ein kleiner Hinweis (am Rande): Das funktioniert natürlich auch ohne das HashSet, indem du vor dem Hinzufügen prüfst, ob die Person schon in der Liste ist. Die HashSet.contains() Methode arbeitet allerdings in O(1), während für ArrayList.contains() O(n) gilt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
L Variable an andere Klasse weitergeben - Was mache ich falsch? Java Basics - Anfänger-Themen 2
berserkerdq2 sqllite in Java, wenn ich mache select count(*) ..., erhalte ich dann nur die gezählte Anzahl oder werden auch die Tabellen ausgegeben? Java Basics - Anfänger-Themen 2
berserkerdq2 Spiel hängt sich immer in der 4 Runde auf, obwohl ich jede Runde das gleiche mache Java Basics - Anfänger-Themen 1
O Ich ahbe einen char und diesen soll ich bei .matches prüfen, also ob der char in meiner Zeichenkette vorhanden ist, wie mache ich das? Java Basics - Anfänger-Themen 9
J Erste Schritte Was mache ich in meinem Code falsch. Java Basics - Anfänger-Themen 3
J Kreis soll die gleiche Fläche wie das Rechteck haben wie mache ich das? Java Basics - Anfänger-Themen 3
J Was mache ich falsch in meiner Java Anwendung? Java Basics - Anfänger-Themen 11
D Guten Tag mache gerade eine Umschulung zum FiSi war leider jetzt 2 Wochen Krank und wir hatten Prozendurale Programmierung. Java Basics - Anfänger-Themen 3
Z Klassen Error: ';' expected - was mache ich falsch? Java Basics - Anfänger-Themen 4
D Probleme beim Kompelieren mache ich etwas falsch ? Java Basics - Anfänger-Themen 3
D Wenn ich repaint(); mache, flackert es so stark, das man fast nichts erkennen kann. Java Basics - Anfänger-Themen 11
A Arrays addieren- Was mache ich falsch?? Java Basics - Anfänger-Themen 2
Silvascus Was mache ich falsch? Java Basics - Anfänger-Themen 15
J Klassen Fehler Datei kopieren - was mache ich falsch Java Basics - Anfänger-Themen 19
G mache aus Test nach sortieren estt oder java aajv Java Basics - Anfänger-Themen 5
K Erste Schritte Wie mache ich weiter? (Spiel-Menü) Java Basics - Anfänger-Themen 9
T Wie mache ich einen Timer der alle 2 sekunden aufgerufen wird? Java Basics - Anfänger-Themen 5
propra Wie mache ich einem JPanel mein bereits instanziertes Model bekannt Java Basics - Anfänger-Themen 9
A Variablen Was mache Ich falsch? Java Basics - Anfänger-Themen 5
B Klassen Wie mache ich das "the java way"? Java Basics - Anfänger-Themen 4
A was mache ich falsch? Java Basics - Anfänger-Themen 3
J Wie mache ich ein JFrame modal Java Basics - Anfänger-Themen 30
D Wie mache ich das? Java Basics - Anfänger-Themen 2
F Ich raffs nicht! - Wie mache ich ein einfaches Java-window? Java Basics - Anfänger-Themen 54
D Muss ein Applet schreiben was Mittelwerte berechnet nur was mache ich falsch? Java Basics - Anfänger-Themen 11
T Was mache ich hier falsch? Java Basics - Anfänger-Themen 3
H Wie mache ich aus pfad\\unterpfad pfad\unterpfad? Java Basics - Anfänger-Themen 3
S Wie mache ich mir eine universelle Timermethode Java Basics - Anfänger-Themen 20
D Brauche mehr Flexibilität bei der Realisierung und weiss nicht wie ich das mache. Java Basics - Anfänger-Themen 10
D Boolean funktioniert nicht, was mache ich falsch? Java Basics - Anfänger-Themen 6
S Deserialisieren: alle Objekte ausgeben - wie mache ich das? Java Basics - Anfänger-Themen 2
M Wie mache ich einen Eventdispatcher? Java Basics - Anfänger-Themen 9
M Counter erstellen - Was mache ich falsch? Java Basics - Anfänger-Themen 17
Q TextArea - wie mache ich einen Absatz? Java Basics - Anfänger-Themen 9
S Fehler in Javaprogramm, was mache ich falsch? Java Basics - Anfänger-Themen 9
T Button Dis/Enablen - Was mache ich falsch? Java Basics - Anfänger-Themen 3
S Was mache ich falsch? Java Basics - Anfänger-Themen 4
D Pascal'sche Drreieck. was mache ich in der ausgabe flasch? Java Basics - Anfänger-Themen 5
D Was mache ich falsch beim ScrollPane ? Java Basics - Anfänger-Themen 2
T Was mache ich falsch? File klasse. Java Basics - Anfänger-Themen 3
G Fehler: Illegal Expression. Was mache ich falsch? Java Basics - Anfänger-Themen 4
W Was mache ich Falsch?? Java Basics - Anfänger-Themen 4
N Womit mache ich ein menue Java Basics - Anfänger-Themen 2
M Länge eines Arrays als Variable speichern möglich? Java Basics - Anfänger-Themen 14
R Liste in Variable speichern Java Basics - Anfänger-Themen 6
J Java long- in int-Variable umwandeln Java Basics - Anfänger-Themen 6
Nitrogames Variablen Variable aus JOptionPane Abfrage in Array einfügen Java Basics - Anfänger-Themen 4
E Variable von 1. Fenster an 2. Fenster übergeben. Java Basics - Anfänger-Themen 7
T Variable in Schleife deklarieren, Speicherplatz, Garbage Collector Java Basics - Anfänger-Themen 10
T Datum als Variable wert Java Basics - Anfänger-Themen 4
G Variable aktualisiert sich nicht in rekursiver Methode Java Basics - Anfänger-Themen 4
R Compiler-Fehler Variable wird nicht gefunden bzw. erkannt? Java Basics - Anfänger-Themen 2
Say super.methode / super.variable und super(variable) Java Basics - Anfänger-Themen 2
M variable in anderer funktion aufrufen Java Basics - Anfänger-Themen 10
N Was Passiert mit dem Namen einer Variable, wenn man diese einer Liste Hinzufügt Java Basics - Anfänger-Themen 16
T Variable von Objekten in einer Methode überprüfen Java Basics - Anfänger-Themen 26
JordenJost char variable funktioniert irgendwie nicht a+b ergibt nicht à Java Basics - Anfänger-Themen 4
M Variable Felderanzahl Java Java Basics - Anfänger-Themen 10
T Variable durch Action Listener ändern Java Basics - Anfänger-Themen 2
stormyark Fehler beim überschreiben einer Variable Java Basics - Anfänger-Themen 1
P Zähler Variable für mehrere Objekte Java Basics - Anfänger-Themen 6
S Eine Variable in einem Array speichern Java Basics - Anfänger-Themen 5
I Methoden Wieso wird mein Array "a" verändert und meine Variable "a" nicht? Java Basics - Anfänger-Themen 4
M Variable in einer Schleife initialisieren Java Basics - Anfänger-Themen 46
W Schleife und einmal variable++ zu viel Java Basics - Anfänger-Themen 20
M String mit Variable vergleichen Java Basics - Anfänger-Themen 9
M Methoden Wert einer Variable geht verloren? Java Basics - Anfänger-Themen 6
G variable kopieren bzw. woanders benutzen Java Basics - Anfänger-Themen 6
Ameise04 Variablen Inhalt einer Variable im Code verwenden? Java Basics - Anfänger-Themen 9
J Double Variable und Addition Java Basics - Anfänger-Themen 2
I Variable innerhalb Methode: Local variable test defined in an enclosing scope must be final or effectively final Java Basics - Anfänger-Themen 3
KogoroMori21 Variable im Parameter und Ohne Java Basics - Anfänger-Themen 5
Vivien Auf eine Variable von einer anderen Klasse aus zugreifen Java Basics - Anfänger-Themen 3
H Datentypen Wertebereich von <Klassenname> <Variable> Java Basics - Anfänger-Themen 12
M Private Variable Java Basics - Anfänger-Themen 2
idontknow707 Matrix nach z.B. Variable durchsuchen Java Basics - Anfänger-Themen 4
T Variable in for Schleife ansprechen ohne Array ? Java Basics - Anfänger-Themen 25
s.marcii Modulo in der Variable einsetzen - ist das möglich? Java Basics - Anfänger-Themen 2
N Variable aus anderen Variablen in statischer Klasse berechnen/abspeichern? Java Basics - Anfänger-Themen 4
Y Wie kann ich die Variable in der Try Catch returnen? Java Basics - Anfänger-Themen 3
K Übergabe des Wertes einer Variable aus main() in eine Klassenmethode Java Basics - Anfänger-Themen 8
B Inkrement von Variable Java Basics - Anfänger-Themen 8
V Variablen statische Variable einer Objektvariable zuordnen Java Basics - Anfänger-Themen 3
L Variable von einer Methode zu einer anderen Methode inkl. einer "Zwischenmethode" Java Basics - Anfänger-Themen 1
J JTextField Bezeichnung als Variable Java Basics - Anfänger-Themen 3
N Wie kann ich eine meine Variable Final machen? Java Basics - Anfänger-Themen 1
NeoLexx Variable für Array wird nicht korrekt übergeben Java Basics - Anfänger-Themen 45
M Enum-Variable HashMap zuweisen Java Basics - Anfänger-Themen 5
H Variable um 1 erhört ausgeben Java Basics - Anfänger-Themen 4
V Erste Schritte Eine Array-Variable mit Benutzereingaben befüllen Java Basics - Anfänger-Themen 3
J Fehlermeldung unklar. non-static variable player0 cannot be referenced from a static context Java Basics - Anfänger-Themen 4
P non-static variable cannot be referenced from a static context Java Basics - Anfänger-Themen 6
A Wie zwei zahlen in einer Variable speichern? Java Basics - Anfänger-Themen 7
W Problem mit dem Wert von boolean-Variable Java Basics - Anfänger-Themen 3
M Input/Output JTextField Eingabe in String Variable speichern Java Basics - Anfänger-Themen 15
A Kann man eine Methode als Variable speichern und danach noch verändern? Java Basics - Anfänger-Themen 6
L cannot find symbol variable Kon Java Basics - Anfänger-Themen 8
C Statischer Typ aber Variable nicht statisch? Java Basics - Anfänger-Themen 5
H Variable.methode aufstellen, verstehen Java Basics - Anfänger-Themen 2
R Warnung, wenn eine Variable eingegeben wird Java Basics - Anfänger-Themen 6

Ähnliche Java Themen

Neue Themen


Oben