Hiermit erstellst du dir eine neue lokale Variable.
Die Assertion überprüft aber die globale Variable buckets von hashMap
Hiermit erstellst du dir eine neue lokale Variable.
Die Assertion überprüft aber die globale Variable buckets von hashMap
Ich vermute, dass das nicht getestet wird, da insertEntry() eigentlich eine interne Methode ist, die nur zu Testzwecken public ist. Da es aber ja kaum Umstände bereitet, kannst du die 2 Zeilen auch vorsichtshalber noch einfügen.
Edit:
Korrektur von mir, gilt auch für alle anderen Globalisierer hier: Global is evil.
A.
Hallo, verweist die Anweisung buckets[0] = buckets[0].nextEntryInBucket zuläassig bzw. kann man danach wie in der Abbildung mit dem Objekt das den Schlüssel c hat als buckets[0] weiterarbeiten?
10.1 j) Annordung
Sollen die Entrys auch neu verteilt werden oder die ketten in der weise kopiert werden wie sie vorher waren? Beispiel
bucket 1 - e1 - e2 -e3
bucket 2 - e4 - e5
bucket 3 - e6
nach Resize(5)
bucket 1 - e1
bucket 2 - e2
bucket 3 - e3
bucket 4 - e4
bucket 5 - e5
oder ist gemeint
bucket 1 - e1 - e2 -e3
bucket 2 - e4 - e5
bucket 3 - e6
bucket 4
bucket 5 ??? irgendwie kann man das ja unterschiedliche interpretieren die Frage…
Ich denke, du musst die Elemente einfach neu einfügen. Da sich die Größe des Arrays ändert, ergibt sich zwangsläufig auch eine neue Berechnung der Position des Elements.
c) nextEntryInBucket
Hallo,
ich bin mir nicht sicher ob ich den zweiten Absatz richtig verstehe. Ist das nur eine allg. Info oder sollen wir jeden Wert der an das Ende der Liste gepackt wurde damit verzeigern?
Ich bin mir nicht sicher, ob ich deine Frage verstanden habe. Aber: die Kollisionsverwaltung passiert in einer einfach verketteten Liste. Dabei werden natürlich Zeiger gesetzt/gewurstelt/entfernt, ohne geht es leider nicht.
A.
Heyho,
ich hätte da auch mal eine Frage:
Habe mein Array exakt so instanziiert, wie auf den Tafelübungsfolien beschrieben und dort auch alle Möglichkeiten durchversucht, also erst Erstellung eines Object Arrays und dann den cast, oder alles in eine Zeile gebracht, Eclipse zeigt mir keinen Fehler mehr an, doch beim Kompilieren bekomme ich eine ClassCastExepetion. Woran könnte das liegen? Die Fehlermeldungen sollten doch eigentlich supressed werden?
T[] array = (T[]) new Object[size];
sicher dass du da nicht irgendwo [ ] vergessen hast?
Es können nur Warnungen unterdrückt werden, keine Compile-Fehler.
A.
hier fehlt doch der new Operator, oder etwa nicht? sonst habe ich es exakt so…
my fault, habs ausgebessert.
Wann genau bekommst du denn nun welche Fehlermeldung? (und vorallem mit welchem Text!)
Das widerspricht sich nämlich, Exceptions kann man nur zur Laufzeit bekommen und nicht beim Übersetzen
Exakt so kann ich mir eigentlich nicht vorstellen. Denn zur Laufzeit wird daraus:
Object[] array = (Object[]) new Object[size];
Dieser Cast sollte eigentlich immer klappen.
Sicher, dass du nicht versuchst beispielsweise ein Array von einer generischen Klasse (beispielsweise Entry) zu erzeugen?
GenericClass<T>[] array = (GenericClass<T>[]) new Object[size];
Denn solche Casts sind in Java zur Laufzeit verboten und werden dir mit einer ClassCastException abstürzen. Erlaubt ist ein Cast nur in den generischen Datentyp (K,V,T, etc.), weil zur Laufzeit dann ohnehin normale Java-Objects draus werden, bei denen der „verbotene“ Cast dann einfach wegfällt (s.o.).
Eine entsprechende Lösung für das GenericType-Array steht auch auf den Übungsfolien:
GenericClass<T>[] array = new GenericClass[size];
Vielen Dank für die aufschlussreichen Antworten schon mal! Ich hab Angst zu viel von der Aufgabe zu verraten, deswegen versuche ich meine Antwort so allgemein wie möglich zu halten^^
CodeMonkey, ich habe es genau so gemacht, wie du es hier zeigst:
1.GenericClass<T>[] array = (GenericClass<T>[]) new Object[size];
Sehe aber den Fehler dahinter nicht und Eclipse meckert auch nicht. GenericClass ist ja eine generische Klasse, die ein Behälter vom Typ T darstellt. Diese Klasse ist doch ein Object und kann demnach auch als Object instanziiert und dann gecastet werden. Ich habe das in der Tafelübung nämlich genau so verstanden, dass man um diesen Cast (GenericClass[]) nicht herumkommt, da man eben ein generisches Array:
GenericClass<T>[] array = new GenericClass<T>[size];
NICHT erstellen kann, da in Java nicht möglich. Auf der Folie zur letztwöchigen Tafelübung (Übung 10) S.62 wird doch genau der Code oben mit Cast als Lösung dargestellt, oder was sehe ich nicht richtig?
@Whitespace:
sorry du hast Recht, ich bekomme beim Kompilieren genau keinen Fehler und Eclipse zeigt mir auch keinen an, zur Laufzeit jedoch bekomme ich eine ClassCastExeption [Ljava.lang.Object can not be cast to LEntry], liegt also schon an der Teilaufgabe a), dass dort meine Initialisierung von dem Array nicht funktioniert, habe dann natürlich aber den gleichen Fehler auch in Resize.
1.GenericClass<T>[] array = new GenericClass[size];
So funktioniert das dann auch bei mir zum Glück, danke! Fehler wurde also behoben und klappt jetzt, ich würde es aber trotzdem gerne noch verstehen.
GenericClass ist doch ein Behälter für den Typ T, also ein Attribut beispielsweise ist vom Typ T und mit Typ T (kann) wird in Methoden gearbeitet. Wobei T hier eigentliches jedes Object sein kann → Prinzip von Generics. So kann man Listen und linkedLists ganz leicht in Java verwirklichen, da für jeden Typ zulässig. Arrays jedoch funktionieren mit Generics nur eingeschränkt, da ja der Compiler eigentlich mit den Generics gar nicht richtig arbeitet, sondern es nur überprüft und dann in Objects umwandelt und davon ausgeht, dass schon alles gut gehen wird^^. Deswegen castet man doch nachträglich noch mal, damit wirklich das richtige Array bei rauskommt. Für mich macht
GenericClass[size]
auch schon einfach deshalb keinen Sinn, weil es doch diese Klasse gar nicht gibt, oder? Es gibt die generische Klasse GenericClass, Behälter mit dem beliebigen Typ T, aber GenericClass wäre in meinen Augen doch eine neue Klasse, die einfach vom Typ GenericClass ist. Ich versuch mich so gut es geht in den Compiler hinein zu versetzten, aber diese Syntax erscheint mir zurzeit noch sehr x-beliebig. Hab also gut was vor über dieses Wochenende
Für mich macht
GenericClass[size]
auch schon einfach deshalb keinen Sinn, weil es doch diese Klasse gar nicht gibt, oder? Es gibt die generische Klasse GenericClass, Behälter mit dem beliebigen Typ T, aber GenericClass wäre in meinen Augen doch eine neue Klasse, die einfach vom Typ GenericClass ist.
[m]GenericClass[/m] ist der Raw Type von [m]GenericClass[/m].
So funktioniert das dann auch bei mir zum Glück, danke! Fehler wurde also behoben und klappt jetzt, ich würde es aber trotzdem gerne noch verstehen.
Ich habe es egtl. in meinem Beitrag schon versucht so zu erklären, dass man es auch verstehen kann.
Wenn du folgenden Code hast, wobei T ein Typparameter für einen generischen Typ ist (beispielsweise das T in GenericClass oder das K und V in eurer HashMap,
T[] myArray = (T[]) new Object[size];
wird nach dem Kompilierungsvorgang daraus mehr oder weniger:
Object[] myArray = (Object[]) new Object[size];
Der Cast ist zur Laufzeit also gar kein richtiger Cast mehr, sondern war nur zur Typsicherung wärend des Kompilierens wichtig. Daher funktioniert das in der Regel ohne Fehler.
Wenn du jetzt allerdings etwas hast, wie:
GenericClass<T>[] myArray = (GenericClass<T>[]) new Object[size];
wird nach dem Kompilierungsvorgang etwa das draus:
GenericClass[] myArray = (GenericClass[]) new Object[size];
All die Typ-Angaben in den spitzen Klammern werden einfach weggelassen, weil diese Typen ja sowieso alle durch Object ersetzt wurden. Und hier sieht man jetzt, dass zur Laufzeit eben durchaus probiert wird zu casten - nämlich ein Object-Array zu einem GenericClass-Array. Diese Art von Casts ist in Java aber nicht erlaubt. Auch ein String[] myArray = (String[]) new Object[size]
wird dir mit einer ClassCastException abstürzen. Solche Casts müssen auf andere Art und Weise realisiert werden (jedes Element aus dem Array casten und in das neue einfügen). Deswegen bricht dein Programm, wenn du das versuchst, mit einer ClassCastException ab.
Eine entsprechende Lösung für das GenericType-Array steht auch auf den Übungsfolien:
GenericClass<T>[] array = new GenericClass[size];
Ach tatsaechlich. Ich habe es zwar auch so rausgefunden, aber das war der versteckte Hint in den Uebungsfolien, wie man das macht … Da hab ich voll drueber hinweg gelesen.
Fehlerbehandlung
Reicht es ni der 10.1 aus, wenn ich nur die in SimpleHashMap angegebenen throws einfüge, oder soll ich z.B. bei insertEntry auch überprüfen ob der index passt?
edit:
noch eine Frage: soll das Programm eigentlich bei einer capacity von 0 (im konstruktor) abbrechen (also mit einer illegalArgumentException)? Und wenn es nicht abbrechen soll , wollt ihr , dass ich in der getBucketIndex eine exception werfe?
Oder kurz : darf ich überhaupt zusätzliche exceptions werfen? Da ja die Doku für dewöhnlich (wenn sie gut ist) das Verhalten des Programms genau wiedergibt.
Wenn ich den folgenden code ausführe,
Entry<Integer, String> e0 = new Entry<Integer, String>(12, "MeinTest", null);
hashMap3.insertEntry(1, e0);
wird der Eintrag e0 an der 1. Stelle im Bucket stehen oder an der 2. Stelle. Bucket hat die Größe 10.