Streams, Enum und Optional - Aufgabe aus Prüfung

DrBronko

Mitglied
Moin moin in die Runde und willkommen zu meiner Aufgabe (für mich) des Grauens.

Mein Name lautet Tobias und ich studiere technische Informatik.
Ich lerne aktuell für meine Prüfung in Objektorientierter Programmierung.

Die letzte Aufgabe der letzten Prüfung sah wie folgt aus und ich verstehe einfach nicht mehr, wie ich ein Optional Objekt aus einem Stream ausgeben soll.
Vielleicht bin ich auch einfach festgefahren, doch auch nach 3 Tagen komme ich keinen Schritt weiter.

Aufgabenstellung:
1706083201367.png

Mein aktueller Ansatz:

package Aufgabe11;

import java.util.Arrays;
import java.util.Optional;

public enum Paket {
S (2),
M (5),
L (10),
XL (25);

private final int maxGewicht;

private Paket(int maxGewicht){
this.maxGewicht = maxGewicht;
}

private int maxGewicht(){
return maxGewicht;
}


private Optional<Paket> paket(double gewicht){

Arrays.stream(Paket.values())
.mapToDouble(n -> n.maxGewicht)
.filter(n -> n / gewicht == 1)
.findAny();

return ...
}
}

Ansonsten werde ich Mut zur Lücke lassen ;-)
 
Zuletzt bearbeitet von einem Moderator:

LimDul

Top Contributor
Grundgedanke ist schon mal nicht schlecht.

Aber es gibt mit deiner Implementierung ein paar Probleme:

a) Die Filter-Bedingung ist falsch. Sie findet z.B. für die Übergabe eines Gewichtes von 12 KG kein Paket. Den keine der Obergrenzen ist 12 KG.
b) findAny ist bei sowas kritisch - was ist, wenn wenn mehrere Pakete passen? z.B. bei einer Übergabe von "3" passt das 5 kg, 10 kg und 25 kg Paket. bei findAny() weißt du nicht, welches zurückkommt - haben willst du das 5kg Paket
c) das mapToDouble() "verliert" dir dein Paket. Du willst den Filter direkt auf das paket Objekt anwenden - dann gibt die dir findFirst/findAny auch direkt das Optional<Paket> zurück

Java:
private Optional<Paket> paket(double gewicht){
return Arrays.stream(Paket.values())
.filter(p->isPaketFuerGewichtGeeignet(p, gewicht))
.sorted(So das das kleinste Paket als erstes steht)
.findFirst()
}

private booelan isPaketFuerGewichtGeeignet(Paket p, double gewicht) {
// TODO :)
}
 

DrBronko

Mitglied
RIESEN DANK schon einmal :) gerade so glücklich, mich hier angemeldet zu haben und direkt eine kompetente Antwort MIT Erklärungen und Hilfestellungen bekommen zu haben.

Das musste einfach gesagt werden!
Danke auch, dass du nicht einfach alles gelöst hast.

Btw kann man den Titel in dem Forum ändern? Da hat sich ja ein Dreher bei Enum eingeschlichen ;-)
 

DrBronko

Mitglied
Grundgedanke ist schon mal nicht schlecht.

Aber es gibt mit deiner Implementierung ein paar Probleme:

a) Die Filter-Bedingung ist falsch. Sie findet z.B. für die Übergabe eines Gewichtes von 12 KG kein Paket. Den keine der Obergrenzen ist 12 KG.
b) findAny ist bei sowas kritisch - was ist, wenn wenn mehrere Pakete passen? z.B. bei einer Übergabe von "3" passt das 5 kg, 10 kg und 25 kg Paket. bei findAny() weißt du nicht, welches zurückkommt - haben willst du das 5kg Paket
c) das mapToDouble() "verliert" dir dein Paket. Du willst den Filter direkt auf das paket Objekt anwenden - dann gibt die dir findFirst/findAny auch direkt das Optional<Paket> zurück

Java:
private Optional<Paket> paket(double gewicht){
return Arrays.stream(Paket.values())
.filter(p->isPaketFuerGewichtGeeignet(p, gewicht))
.sorted(So das das kleinste Paket als erstes steht)
.findFirst()
}

private booelan isPaketFuerGewichtGeeignet(Paket p, double gewicht) {
// TODO :)
}

Wenn noch einmal im Laufe des Tages Zeit hast drüber zu schauen.
Müsste doch so passen oder?

Java:
package Aufgabe11;
import java.util.Arrays;
import java.util.Optional;

public enum Paket {
S (2),
M (5),
L (10),
XL (25);

private final int maxGewicht;

private Paket(int maxGewicht){
this.maxGewicht = maxGewicht;
}

private int maxGewicht(){
return maxGewicht;
}


private boolean istPaketFuerGewichtGeeignet(Paket paket, double gewicht){

boolean istGeeignet = false;
if(((int)((double)paket.maxGewicht / gewicht)) == 1){
istGeeignet = true;
}
return istGeeignet;
}


private Optional<Paket> paket(double gewicht) {

return Arrays.stream(Paket.values())
.filter(p -> istPaketFuerGewichtGeeignet(p, gewicht))
.sorted()
.findFirst();

}
}
 

KonradN

Super-Moderator
Mitarbeiter
Btw kann man den Titel in dem Forum ändern? Da hat sich ja ein Dreher bei Enum eingeschlichen ;-)
Du kannst eigene Beiträge nur 30 Minuten lang editieren. Den Titel oder so kann sonst nur ein Moderator anpassen und ich war mal so frei, da es Dich gestört hat.

Müsste doch so passen oder?
Hast Du es einfach einmal ausprobiert? Das wäre immer das Einfachste.

Was ich sehe ist, dass Du .sorted aufrufst ohne vorzugeben, wie das Enum sortiert werden soll. Das sieht so also erst einmal nicht korrekt aus.
Aber da die Einträge im Enum sortiert eingetragen werden sollen, kann das Sortieren aus meiner Sicht entfallen.

Wenn Du es aber sortieren willst, dann kannst du einen Comparator angeben, also ein Comparator.comparingInt(Paket::maxGewicht) oder so ähnlich (jetzt so aus dem Kopf geschrieben)
 

mihe7

Top Contributor
Müsste doch so passen oder?
Deine Bedingung ist immer noch falsch und unnötig kompliziert:
Java:
((int) ((double)paket.maxGewicht / gewicht)) == 1

Die Typumwandlung auf double is unnötig, da gewicht bereits double ist. Das aber nur nebenbei.

Du teilst das Paketgewicht durch ein gegebenes Gewicht und prüfst, ob das ganzzahlige Ergebnis 1 ist, d. h. das Ergebnis der double-Division muss zwischen 1.0 (incl.) und 2.0 (excl.) liegen:
Java:
paket.maxGewicht / gewicht >= 1.0 && paket.maxGewicht / gewicht < 2.0
Multipliziert mit gewicht:
Java:
paket.maxGewicht >= gewicht && paket.maxGewicht < 2*gewicht
Die letzte Bedingung führt nun dazu, dass gewicht mindestens (EDIT: größer als) die Hälfte des Paketgewichts sein muss. Möchtest Du also etwas mit einem Gewicht von 0.5 versenden, findest Du kein passendes Paket.

Nachtrag:
Deine if-Konstruktion ist auch zu kompliziert. Deine Bedingung liefert bereits ein boolean, und das Ergebnis entspricht genau diesem. Es reicht also
Java:
return paket.maxGewicht >= gewicht;
zu schreiben.
 

KonradN

Super-Moderator
Mitarbeiter
da ich ja sowieso nur ein passendes Element finde.
Nein, natürlich bekommst Du auch mehrere passende Elemente. Wenn Du ein Gewicht von 1g hast, dann kannst Du das in jedem Paket versenden.
Es wird aber natürlich das "kleinste" Paket gewünscht.

Und das sort darf nur entfallen, weil in der Aufgabe gesagt wurde:
1706104783545.png

Das ist etwas, das ich als Entwickler aber nie voraus setzen würde. Und bei den paar Elementen kostet das sort doch nichts und es verhindert einen dummen, ggf. schwer zu sehenden Fehler! Daher das entsprechende sort mit Angabe eines Comparators.
 

mihe7

Top Contributor
Okay, @DrBronko es gibt hier jemanden, bekannt als Tobias, mit - sagen wir mal - speziellem Verhalten, wobei das Highlight das Verhältnis zu Konrad ist (führt dann zu äußerst amüsanten Diskussionen -> Popcorn herrichten). Es dauert in der Regel ein bis zwei Tage, bis Tobias erkannt und gesperrt wird (bis zur nächsten Neuanmeldung). Insofern ist es mutig, sich hier mit diesem Namen zu vorzustellen :)
 

DrBronko

Mitglied
Das klingt mir ganz nach einem aus meinem Studium, aber das wird ja wohl nicht sein. Er eckt in unserem Discord auch oft genauso an. Bin mir aber nicht sicher, ob er noch studiert oder nur den Discord verlassen musste.

So, nun zur eigentlichen Lösung.
Die Methode im Filter kann ich mir ja wirklich sparen, wenn ich einfach nur:


Java:
    public static Optional<Paket> paket(double gewicht) {
        return Arrays.stream(values())
                .filter(p -> gewicht <= p.maxGewicht())
                .findFirst();
    }

benutze oder wie in dem Fall von mihe7
Java:
return paket.maxGewicht >= gewicht;

Und klar, dass mit dem Double Cast hätte ich mir sparen können.
Der eine Wert ist es ja schon und dann wird der int ja automatisch zum Double.
 

KonradN

Super-Moderator
Mitarbeiter
Ja das sieht vom Code her ok aus.

Das andere Thema würde mich fast reizen, aber auf der anderen Seite: Ich will ja eigentlich keine Zeit darauf verschwenden. Aber so eine ladungsfähige Adresse von unserem Troll wäre schon etwas ... :)
 

Neue Themen


Oben