wenn ich in der main Methode 2 Studenten mit verschiedene namen und gleiche matrikelnummer immnatrikulieren lasse, wird beide immatrikuliert, dabei habe ich in der Klasse Student equals methode überschrieben. Gleichheit wird auf matrikelnummer geprüft
Ich habe Studenten auf der uni und ich möchte Exmatrikulieren
ausgabe ist Der student mit Matrikelnummer 9874521 existiert nicht
Wo liegt mein Fehler?
//Bitte beachtet meine Exceptions nicht. Das thema habe ich nicht ganz dzúrch
In der Klasse Student in Zeile 41: if(getMatrikelnummer() == stud.getMatrikelnummer()){
Strings werden nicht mit dem Vergleichsoperator verglichen, da dieser bei Objekten auf die Identität prüft und nicht auf Gleichheit (wie man vermuten könnte). Bei Objekten immer die methode equals benutzen. if(getMatrikelnummer().equals(stud.getMatrikelnummer())) {
hashCode() sieht noch schön doof aus … so punkt vor strich und so …
und equals() … naja … lieber erst prüfen was alles nicht equal ist und überall return false anstatt einmal sauber alles prüfen … und nur einmal jeweils return true / false … weis net was clean code zu sagt … die ursprüngliche variante von TO lässt sich aber einfacher verstehen
[QUOTE=Unregistriert]hashCode() sieht noch schön doof aus … so punkt vor strich und so …
und equals() … naja … lieber erst prüfen was alles nicht equal ist und überall return false anstatt einmal sauber alles prüfen … und nur einmal jeweils return true / false … weis net was clean code zu sagt … die ursprüngliche variante von TO lässt sich aber einfacher verstehen[/QUOTE]
…und Du bist hier nicht angemeldet. Sende Deine Beschwerde doch an NetBeans, vielleicht hören die auf Dich (nicht.)
contains ruft die equals methode auch. Equals methode ist in der Klasse Object schon definiert, aber man muss meistens überschreiben, wenn man die benutzen will, weil in der subklasse definierte methode lediglich die adressen der Objekte vergleicht?
[QUOTE=SlaterB]für eigene Klassen gilt das in der Regel,
für API-Klassen wie String offensichtlich schon vorhanden, sonst könnte man auch nichts dran ändern[/QUOTE]
danke
endlich was richtig verstanden und kann ich wenigsten Thema abhacken
if (matrikelnummer == null || !MAT_PAT.matcher(matrikelnummer).find()) {
throw new IllegalArgumentException("wrong mat: " + matrikelnummer);
}
this.matrikelnummer = matrikelnummer;
}
@Override
public int hashCode() {
// matrikelnummer kann nicht null sein:
return matrikelnummer.hashCode();
}
@Override
public boolean equals(Object obj) {
// this.matrikelnummer kann nicht null sein:
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Student other = (Student) obj;
return this.matrikelnummer.equals(other.matrikelnummer);
}```
oder
``` @Override
public int hashCode() {
// matrikelnummer kann nicht null sein
// und enthält nur 0 - 9
// und ist nicht negativ oder größer (2^31)-1 :
return Integer.valueOf(matrikelnummer);
}```
Evtl. noch den Pattern anpassen, wenn vorne z. B. keine 0 stehen darf, oder mit einer Schleife über matrikelnummer iterieren oder Integer.valueOf(matrikelnummer) verwenden.
von Hash Code habe ich wirklich keine Ahnung..
Viele Grüße!
[QUOTE=anni80]Danke für die Erklärung. Das ist noch chinesisch für mich. komme sicherlich nach einpaar Monaten zu deinem Code
lg anni[/QUOTE]
Es kommt darauf an, welche Vorgaben ihr für die Matrikelnummer bekommen habt: keine 0 vorne, (und) nur aus dem Bereich xy bis za oder nur Primzahlen etc. pp. Ich kenne die Aufgabenstellung ja nicht.
hashCode() wird eigentlich „nur“ bei einer Set/Map benötigt. Eine (verkettete) Liste kann ja nur für jedes Element equals() aufrufen (über die Liste iterieren).
Es ist richtig, alle Klassen erben implizit von der Klasse Object, in Object ist equals() implementiert, aber nur so, dass auf ich nehme an referenzielle Gleichheit (Identität) überprüft wird.
Ich hab’ das mal vollständig neu geschrieben und die Klasse Uni Thread-sicher gemacht (welche Interfaces man u. a. implementieren könnte, sind angegeben):
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication1;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* @author ikwudls
*/
public class Uni /* implements Iterable<Uni.Student>, Serializable */ {
public static class Student /* implements Comparable<Student>, Serializable, .... */ {
/**
* 1000 - 999999 (both inclusive)
*/
private static final Pattern MAT_PAT = Pattern.compile("^[1-9]\\d{3,5}$");
private String vorname;
private String nachname;
private String matrikelnummer;
public Student(String vorname, String nachname, String matrikelnummer) {
this.vorname = vorname;
this.nachname = nachname;
setMatrikelnummer(matrikelnummer);
}
public String getVorname() {
return vorname;
}
public void setVorname(String vorname) {
this.vorname = vorname;
}
public String getNachname() {
return nachname;
}
public void setNachname(String nachname) {
this.nachname = nachname;
}
public String getMatrikelnummer() {
return matrikelnummer;
}
/**
* 1000 - 999999 (both inclusive)
*
* @param matrikelnummer
*/
public final void setMatrikelnummer(String matrikelnummer) {
if (matrikelnummer == null || !MAT_PAT.matcher(matrikelnummer).find()) {
throw new IllegalArgumentException("wrong matrikelnummer: " + matrikelnummer);
}
try {
Integer.valueOf(matrikelnummer);
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException("wrong matrikelnummer: " + matrikelnummer);
}
this.matrikelnummer = matrikelnummer;
}
@Override
public int hashCode() {
return Integer.valueOf(matrikelnummer);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Student other = (Student) obj;
return this.matrikelnummer.equals(other.matrikelnummer);
}
@Override
public String toString() {
return "Student{" + "vorname=" + vorname + ", nachname=" + nachname + ", matrikelnummer=" + matrikelnummer + '}';
}
}
private final List<Student> studenten = new ArrayList<Student>(4000);
public void im(Student stud) {
if (stud == null) {
throw new IllegalArgumentException("stud ist null: " + stud);
}
synchronized (studenten) {
if (studenten.contains(stud)) {
for (Student student : studenten) {
if (stud.equals(student)) {
throw new IllegalArgumentException(stud + " bereits vorhanden: " + student);
}
}
}
studenten.add(stud);
}
}
public void em(Student stud) {
if (stud == null) {
throw new IllegalArgumentException("stud ist null: " + stud);
}
synchronized (studenten) {
if (!studenten.contains(stud)) {
throw new IllegalArgumentException(stud + " nicht vorhanden");
}
studenten.remove(stud);
}
}
@Override
public String toString() {
int i = 1;
StringBuilder builder = new StringBuilder();
synchronized (studenten) {
for (Student student : studenten) {
builder.append(String.format("% 7d: %s%n", i++, student));
}
}
return builder.toString();
}
public static void main(String[] args) {
Uni u = new Uni();
System.out.println(u);
u.im(new Student("Thom", "Müller", "1234"));
u.im(new Student("keine", "Ahnung", "4321"));
u.im(new Student("mir-fällt", "nix-ein", "1111"));
System.out.println(u);
try {
u.im(new Student(null, null, "4321"));
} catch (IllegalArgumentException iae) {
System.out.println(iae);
}
u.em(new Student(null, null, "4321"));
System.out.println(u);
}
}```
Aber jetzt soll mit der Liste studenten ja auch etwas gemacht werden, deshalb dafür Methoden einfügen.
du definierst einen int mit einem wert : 5
und schreibst ne rechnung dazu : 89 * 5 + X
was wird jedes grundschulkind machen ? richtig : 89 * 5 auflösen , was auch mathematisch korrekt ist , dann X (falls komplexer term) und erst ganz zum schluss die addion
ich will mich hier nicht drüber streiten wie ichs dir versucht hab einfach klar zu machen , und kann deine reaktion auch nicht verstehen , aber einfach erstmal alles auf die IDE zu schieben anstatt mal selber das hirn anzuschalten dass das was die IDE da als default-template hat so ziemlicher käse ist … naja , man weis ja was drüben passiert ist
auch wurde ja bereits im anderen thread genannt : “hashCode() wird in der regel ein mal berechnet und dann gecachet”
gut : so ziemlich alles in der API hält sich nicht dran, aber wenn man selbst was schreibt könnte man mehrfaches neu-erzeugen, berechnen und wieder wegwerfen durch aus optimieren , sonst kann auch aus einer simplen hashCode() mal eben ein speicher-leak werden
und zu deiner anderen diskusion
Integer.parseInt() bzw Integer.valueOf() hat ja nun mal einen ganz anderen sinn als hashCode()
warum du also versuchst beide miteinander zu vergleichen wird zumindest mir nicht klar , vielleicht versuchst du ja es mir zu erläutern
Also zu deiner eigentlichen Frage müsste ich auf die Definition eines Hashwertes/codes eingehen, wovon ich aber, wie erwähnt, keine Ahnung habe.
Zu der anderen Frage: Es geht um den Wert eines primitiven (Variablen)-Typs und aus einer Berechnung x * y + z. klar, die kann man cachen (also: speichern), allerdings weiß ich nicht, ob das explizit den Flaschenhals vermeiden würde:
return val;
}
return (val = x*y+z);```
Geschwindigkeitsvorteil, wenn doch immer "not equal to " ausgeführt werden muss?
Wegen dessen, was die IDE produziert, musst du dich, wie erwähnt, nicht bei mir beschweren; ich geb' aber zu, dass ich das ohne "scharfes Hinsehen" einfach so übernommen hab'.
sicherlich , ich hab ja auch erwähnt das ich nicht weis was z.b. “clean code” zu sagt (da ichs einfach immer noch nich gepackt hab mir das zu bestellen , vielleicht mal zu x-mas) , und ich gehe schon von aus das sich irgendwer bei dieser implementierung was gedacht haben wird , aber es ist schon irgendwie murks , und wirklich leserlich bzw leicht zu verstehen ist es auch nicht
gucken wir uns mal einige hash-algorithmen an : in der regel wird erst gepaddet und dann in einem loop blockweise miteinander verrechnet um eine feste ergebnislänge zu erhalten
man könnte nun z.b. alle member irgendwie bis auf ihre primitives runterbrechen (am einfachsten durch wiederum ähnlich implementierte hashCode() methoden) so das man diese in eine rechnung stecken kann
wenn man die regel : “gleicher inhalt erzeugt gleichen hashCode()” aufstellt so kann man für equals() angeben : wenn beide objekte nicht null sind , vom gleichen type sind und den gleichen hashCode() haben sind sie equals() , sonst nicht
was in code dann recht einfach mit einer prüfung auf NULL , auf instanceof und int==int umzusetzen ist
finde ich persönlich jetzt deutlich einfacher zu lesen und zu verstehen als das was netbeans da hingekleistert hat
aber naja , wir werden ziemlich OT
das grundproblem von TO war ja das er zwei objekte mit “==” statt equals() verglichen hat , womit seine eigene equals() nun mal fehlerhaft implementiert war