Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Wie kann ich den Index i von einer LinkedList überprüfen?
bei einem Array kann man mit Hilfe einer for-Schleife ja durch das Array iterieren, um dann zum Beispiel bei array(3) zu überprüfen, ob der Wert z.B. 4 ist.
Wie kann ich den Index i von einer LinkedList überprüfen? Hab nicht wirklich gefunden was ich Suche.
Also generell solltest Du wissen, was in der LinkedList ist. Dazu dienen ja die Generics. Das hat den Hintergrund, dass man in der Regel typsicher entwickeln möchte.
Aber wenn Du nicht weisst, was drin ist, dann kannst Du mit instanceof prüfen, ob das Element z.B. vom typ einer Enum ist. Also etwas wie: if (list.get(i) instanceof MyEnum)
Es geht um eine Art Filterfunktion. Ich möchte überprüfen, ob auf der Liste Elemente aus dem Enum vorhanden sind.
Wenn ich dazu .equals() verwenden kann erschließt sich mir der richtige Syntax nicht ganz
public enum Allergen {
NUTS, PEANUTS, SOYBEANS, GLUTEN, FISH, MILK, EGGS;
}
import java.util.LinkedList;
abstract class Item implements ItemInfo {
private double price;
private int ID;
private LinkedList<Allergen> allergenes = new LinkedList<Allergen>();
public double getPrice() {
return price;
}
public int getID() {
return ID;
}
public LinkedList<Allergen> getAllergenes() {
return allergenes;
}
public void setPrice(double price) {
this.price = price;
}
public void setID(int iD) {
ID = iD;
}
public void setAllergenes(LinkedList<Allergen> allergenes) {
this.allergenes = allergenes;
}
}
import java.util.LinkedList;
public class StorageManager extends Employee {
private LinkedList<Item> items = new LinkedList<Item>();
public boolean buyNewItem(Object Item) {
if (items.contains(Item)) {
return false;
} else {
items.add((Item) Item);
return true;
}
}
public LinkedList<Item> filterStorage() {
LinkedList<Item> newItems = new LinkedList<Item>();
for (int i = 0; i < items.size(); i++) {
//Hier muss überprüft werden, ob die Allergene aus dem Enum
// "Allergen" in der Liste vorhanden sind, wenn ja sollen diese
//in "newItems" kopiert werden.
newItems.add(items.get(i));
}
return newItems;
}
public LinkedList<Item> getItems() {
return items;
}
public void setItems(LinkedList<Item> items) {
this.items = items;
}
}
Das dürften alle relevanten Teile vom Code sein. "Der StorageManager moechte alle Artikel (items) filtern. Als Filter dient hier ein Objekt aus dem Enum Allergen. Es soll jedes Item, welches den Filter in seiner allergen-Liste enthaelt, in eine neue LinkedList kopiert werden. Diese soll am Ende zurueckgegeben werden."
Würde ich aus genau dem Grund nicht mit Objects.equals machen: entweder die Liste soll null enthalten, dann lieber mit !=null explizit machen, oder da soll fachlich kein null drin sein, dann equals und durch die NPE den Fehler damit wenigstens finden können.
Es soll jedes Item, welches den Filter in seiner allergen-Liste enthaelt, in eine neue LinkedList kopiert werden. Diese soll am Ende zurueckgegeben werden.
Würde ich aus genau dem Grund nicht mit Objects.equals machen: entweder die Liste soll null enthalten, dann lieber mit !=null explizit machen, oder da soll fachlich kein null drin sein, dann equals und durch die NPE den Fehler damit wenigstens finden können.
Eine NPE ist eine EntwicklerZuBlödException, dass hat nichts mit Fehlersuche zu tun. Für die Fehlersuche würde sich z.B.: Objects.requireNonNull(String obj, String message), eine Assertition oder eine Annotation anbieten. Objects.equals macht den Quellcode lesbarer, als X-mal den Ausdruck: (a == b) || (a != null && a.equals(b)) einzufügen.
Wie ich das sehe sind die Enum/Allergene immer in der Liste vorhanden, da Item#getAllergenes() ja immer eine LinkedList<Allergen> zurückgibt.
Java:
public LinkedList<Item> filterStorage() {
LinkedList<Item> newItems = new LinkedList<Item>();
for (int i = 0; i < items.size(); i++) {
//Hier muss überprüft werden, ob die Allergene aus dem Enum
// "Allergen" in der Liste vorhanden sind, wenn ja sollen diese
//in "newItems" kopiert werden.
newItems.add(items.get(i));
}
return newItems;
}
Die einzige Möglichkeit wäre, dass die Liste null oder empty ist, ansonsten müssen da immer Allergene drin sein.
Java:
List<?> list = items.get(i).getAllergenes();
if (list != null && !list.isEmpty()) {
// list contains Allergenes
}
Eine NPE ist eine EntwicklerZuBlödException, dass hat nichts mit Fehlersuche zu tun. Für die Fehlersuche würde sich z.B.: Objects.requireNonNull(String obj, String message), eine Assertition oder eine Annotation anbieten.
Mein "Fehler finden" ist eher als ein "Fehler anzeigen, damit man merkt, dass an anderer Stelle ein Fehler gemacht wurde"
Es kann ja nur zwei Fälle geben: 1) die Liste kann fachlich null enthalten, oder 2) sie kann es nicht (und null in der Liste wäre ein Fehler)
In Fall 1 würde ich das explizit machen, mit Objects.equals rätseln man sonst beim Lesen nur, ob es nur einfach so "um auf Nummer sicher zu gehen" ist, oder weil es fachlich nötig ist (und wenn ja, ob es fachlich an der Stelle auch nötig ist, dass null==null).
Und in Fall 2 würde ich dort explizit keinen Check machen, ein zusätzlicher Check würde den Fehler (der an anderer Stelle gemacht wurde) nur noch weiter verschleiern, und "Mehraufwand", der das Entdecken von Fehlern schwieriger macht, klingt nicht wirklich sinnvoll.
Klar, kann man dort dann auch mit Objects.requireNonNull machen, der Unterscheid ist aber marginal und bläht den Code unnötig auf
Aber nicht ausschließlich eigentlich? Ich hatte schon den Fall das alle Eingaben die der Public Test macht in die neue Liste kopiert wurden, das waren 5 glaub ich, es sollen aber wohl nur 2 sein
Java:
1) testStorageManagerFilterStorage(PublicTests)
java.lang.AssertionError: expected:<[Food@ba4d54, Food@12bc6874]> but was:<[]>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
at PublicTests.testStorageManagerFilterStorage(PublicTests.java:183)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:52)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:77)
at org.junit.runner.JUnitCore.main(JUnitCore.java:36)
Ich hatte schon den Fall das alle Eingaben die der Public Test macht in die neue Liste kopiert wurden, das waren 5 glaub ich, es sollen aber wohl nur 2 sein
Wenn in der Liste immer 2 Elemente sein sollen, dann ist eine Liste möglicherweise der falsche Objekttyp. Eine Datenstruktur fester Länge wäre z.B.: ein Array.
Dein AssertionError sagt außerdem, dass eine leere Collection gefunden wurde.
Es sollen nicht immer 2 Elemente sein. Es geht ja darum aus der Liste "items" die Item rauszufiltern, die Allergene sind, diese sollen dann in eine neue Liste kopiert werden. Der Public Test gibt der Liste in dem Fall wie gesagt 5 Items, wovon zwei dann Allergene sind. Ich kriege es nur nicht hin, diese zwei Allergene rauszufiltern.
Es sollen nicht immer 2 Elemente sein. Es geht ja darum aus der Liste "items" die Item rauszufiltern, die Allergene sind, diese sollen dann in eine neue Liste kopiert werden. Der Public Test gibt der Liste in dem Fall wie gesagt 5 Items, wovon zwei dann Allergene sind. Ich kriege es nur nicht hin, diese zwei Allergene rauszufiltern.
Wenn ich damit versuche irgendwas zu erreichen scheitert es am getAllergenes() und jegliche Änderung die von Eclipse vorgeschlagen wird ist gegen die "Regeln" der Aufgabe.
public LinkedList<Allergen> filterStorage(Allergen ALLERGEN) {
LinkedList<Allergen> list = new LinkedList<Allergen>();
for (int i = 0; i < items.size(); i++) {
list = items.get(i).getAllergenes();
if ((list != null) && !list.isEmpty()) {
list.add(ALLERGEN);
}
} return list;
}
Jetzt habe ich schonmal wenigstens etwas in der neuen Liste, aber noch nicht das richtige:
Java:
There was 1 failure:
1) testStorageManagerFilterStorage(PublicTests)
java.lang.AssertionError: expected:<[Food@ba4d54, Food@12bc6874]> but was:<[FISH, SOYBEANS, EGGS, GLUTEN]>
Ich muss ALLERGEN ersetzten und sowie es aussieht mit einer Liste(?), nur das wie erschließt sich mir wieder nicht
Keine Ahnung, was das werden soll, aber so wie es aussieht vergleicht dein "asserEquals" eine Liste von Items mit einer Liste von Allergenen. Wie soll das jemals gleich sein? Das ist der Vergleich von Äpfeln mit Birnen.
BTW: Um Objekte mit equals() zu vergleichen, müssen sie natürlich equals() überschreiben. Sonst wird die von Object geerbte equals()-Methode verwendet und die macht vermutlich nicht, was du möchtest. Wie du auch an deiner Ausgabe erkennen kannst, werden da nur die Hashwerte (auch die Standard-Implementierung von Object) verglichen. Als generelle Regel gilt. Wer equals() überschreibt sollte auch hashCode() überschreiben.
Hier ein einfaches Beispiel. Als Kriterium für die Identität wird hier die Instanzvariable type verwendet. Das ist aber allein deine Entscheidung, was genau die Identität deiner Objekte ausmacht. Sowohl hashCode() als auch equals() wurden von meiner IDE automatisch erzeugt.
Java:
public class Auto {
private String type;
public Auto(String type) {
this.type = type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Auto auto = (Auto) o;
return type != null ? type.equals(auto.type) : auto.type == null;
}
@Override
public int hashCode() {
return type != null ? type.hashCode() : 0;
}
public static void main(String[] args) {
Auto audi = new Auto("Audi");
Auto opel = new Auto("Opel");
Auto nochEinAudi = new Auto("Audi");
System.out.println(audi.equals(opel));
System.out.println(audi.equals(nochEinAudi));
}
}
Also der Public Test ist nicht von mir, der ist von der Uni. Dachte nur, dass der vielleicht noch einen Anhaltspunkt liefern könnte. Soweit funktioniert die Methode, nur nicht so wie sie soll. ALLERGEN muss ich ersetzten, wie gesagt, ich weiß nur nicht wodurch.
"gluten" ist eine Liste von Items (die Gluten enthalten). Die soll verglichen werden (und gleich sein) mit dem Ergebnis von s.filterStorage(Allergen.GLUTEN) . Das muss also ebenfalls eine Liste von Items sein (die Gluten enthalten).
Deine Methode filterStorage() liefert allerdings eine Liste von Allergenen zurück.
Das hatte ich vorher, dass die Methode eine Liste von Items zurück gibt (LinkedList<Item>), dann bekomme ich aber bei getAllergenes(): Type mismatch: cannot convert from LinkedList<Allergen> to LinkedList<Item>, was mir noch logisch erscheint.
Aktuell bin ich bei diesem Stand:
Java:
public LinkedList<Item> filterStorage(Allergen ALLERGEN) {
LinkedList<Item> list = new LinkedList<Item>();
for (int i = 0; i < items.size(); i++) {
list.add(items.get(i));
//filter? "if" Bedingung? Was anderes?
} return list;
}
Damit bekomme ich diese Ergebnis, sieht eigentlich ja so aus, als wäre ich auf dem richtigen Pfad, nur wie oben im Kommentar angemerkt, fehlt mir noch die richtige Bedingung und was dann ausgeführt werden soll. Es fehlt noch der Filter.
Überschreib doch mal die Methode toString() von Food und lass dir dort einen sinnvollen Text zurück geben, z. B. den Namen des Lebensmittels.
EDIT: Ich sehe grade, dass es anscheinend kein sinnvolles Feld gibt, das man da verwenden könnte. Also vergiss das erst mal.
Dann lässt sich das Ergebnis des fehlgeschlagenen Tests vermutlich viel besser lesen.
Und die Bedingung ist doch klar, du sollst alle in dem StoreManager enthaltenen Lebensmittel, die das als Parameter übergebenen Allergen enthalten, zurück geben.
Du musst also durch alle Items gehen und z. B. mit contains() prüfen, ob es in dessen Allergenliste enthalten ist.
Ich meinte nur, dass mir die Bedingung in Codeform überhaupt nicht klar ist. Das ist der Stand und das müsste für mein Verständnis doch klappen, tut es aber nicht. Oder ist ALLERGEN in diesem Fall nur ein Element aus dem Enum Allergen und nicht alle?
Für mein Verständnis würde die if Bedingung hier das Element an Stelle i mit dem Enum vergleichen und dieses Element dann in list hinzufügen, wenn es true ist?
Java:
public LinkedList<Item> filterStorage(Allergen ALLERGEN) {
LinkedList<Item> list = new LinkedList<Item>();
for (int i = 0; i < items.size(); i++) {
if (items.get(i).equals(ALLERGEN)) {
list.add(items.get(i));
}
} return list;
}
"items" ist eine Liste von Items, demnach liefert dir items.get(i) ein einzelnes Item. Du versuchst ein Item mit einem Allergen zu vergleichen. Das sind wieder Äpfel und Birnen.
Du möchtest für jedes Item, dessen Liste von Allergenen prüfen, ob das bestimmte Allergen darin enthalten ist.
Dann versuche die Bedingung, bzw. den Algorithmus erst mal ohne Code ganz einfach in Worte zu fassen: "Für jedes Item in der Liste.."
Wenn das gut gemacht ist, dann kannst du es 1:1 in Code übersetzen.
Ich würde dir auch die for-each-Schleife (bzw. enhanced for-Loop) ans Herz legen. Damit iterierst du über alle in der Liste enthaltenen Elemente:
Java:
public LinkedList<Item> filterStorage(Allergen allergen) {
LinkedList<Item> result = new LinkedList<Item>();
for (Item item : items) {
// mach was mit dem item
}
return result;
}
Das hat die Lösung gebracht Danke
Auch wenn es nicht so gedacht war, funktioniert. getAllergenes() hatte ich gar nicht mehr auf dem Schirm weil es bei meinen vorherigen Versuchen immer zu irgendwelchen Errors geführt hat.
Java:
public LinkedList<Item> filterStorage(Allergen ALLERGEN) {
LinkedList<Item> list = new LinkedList<Item>();
for (Item item : items) {
if (item.getAllergenes().contains(ALLERGEN)) {
list.add(item);
}
} return list;
}
Noch ein Hinweis: Methoden- und Variablennamen (und da gehören auch die Namen von Parametern dazu) beginnen in Java mit einem Kleinbuchstaben. Sog. lowerCamelCase.
Komplett groß werden i.d.R. nur Konstanten geschrieben. Evtl. auch noch die Werte einer Enumeration.