Collections Streams - Hilfestellung bei komplexer Struktur

B

Bela B.

Aktives Mitglied
Hallo zusammen,

ich bin gerade dabei, mir Streams beizubringen. Nachdem ich Lambdas nun verstanden und selbstständig anwenden und die Vorteile erkennen kann, hadere ich gerade dabei mit der richtigen Verwendung von Streams.

In meinem aktuellen Fall habe ich folgende Situtation:
Klasse MeasurementPoint, beschreibt einen Messpunkt in meinen Daten
Java:
public class MeasurementPoint {
    private final LocalDateTime timestamp;
    private final Double temperature;

    public MeasurementPoint(LocalDateTime timestamp, Double temperature) {
        this.timestamp = timestamp;
        this.temperature = temperature;
    }

    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    public Double getTemperature() {
        return temperature;
    }

    @Override
    public String toString() {
        return "MeasurementPoint{" +
                "timestamp=" + timestamp +
                ", temperature=" + temperature +
                '}';
    }
}

Klasse ChannelPoint, beschreibt einen Messlauf in meinen Daten, ein Kanalpunkt besteht also aus mehreren Measurementpoints, je nach Anzahl der Messfühler:
Java:
public class ChannelPoint {
    private final LocalDateTime timestamp;
    private final List<MeasurementPoint> measurementPoints;

    public ChannelPoint(LocalDateTime timestamp, List<MeasurementPoint> measurementPoints) {
        this.timestamp = timestamp;
        this.measurementPoints = measurementPoints;
    }

    public Double getTemperatureMax() {
        Optional<MeasurementPoint> result = measurementPoints.stream()
                .max(Comparator.comparing(MeasurementPoint::getTemperature));
        return result.isPresent() ? result.get().getTemperature() : 0.0;
    }

    public Double getTemperatureMin() {
        Optional<MeasurementPoint> result = measurementPoints.stream()
                .min(Comparator.comparing(MeasurementPoint::getTemperature));

        return result.isPresent() ? result.get().getTemperature() : 0.0;
    }

    public List<MeasurementPoint> getMeasurementPoints() {
        return measurementPoints;
    }

    @Override
    public String toString() {
        return "ChannelPoint{" +
                "timestamp=" + timestamp +
                ", measurementPoints=" + measurementPoints +
                '}';
    }
}

Dazu habe ich dann jetzt einen Check, der auf den eingelesenen ChannelPoints arbeiten soll.
Bei diesem speziellen Check geht es darum, dass die Temperatur für einen Zeitraum t zwischen den Temperaturen Tmin und Tmax sich befinden muss.

Ich hätte das jetzt auf zwei vom Interface Check implementierenden Klassen gelöst. Der erste Check überprüft also nur, welche ChannelPoints zwischen Tmin und Tmax liegen.

TempMinMaxCheck:
Java:
public class TempMinMaxCheck implements Check{

    private final Profile profile;
    private final String checkName;
    private final Double tempMin;
    private final Double tempMax;
    private final Duration duration;

    private ChannelPoint start;
    private ChannelPoint end;

    public TempMinMaxCheck(Profile profile, String checkName, Double tempMin, Double tempMax, Duration duration) {
        this.profile = profile;
        this.checkName = checkName;

        this.tempMin = tempMin;
        this.tempMax = tempMax;
        this.duration = duration;
    }

    @Override
    public boolean execute() {
        // ---- hier soll dann über Stream überprüft werden, welche Punkte in dem Temperaturbereich liegen, gleichzeitig soll hier dann ChannelPoint start und ChannelPoint end gesetzt werden. start ist der erste ChannelPoint, bei dem alle MeasurementPoints größergleich Tmin sind, end entsprechend der ChannelPoint, bei dem mindestens ein MeasurementPoint vom ChannelPoint größer Tmax oder aber kleiner Tmin ist.
        );

        return false;
    }

    @Override
    public String getCheckName() {
        return null;
    }

    @Override
    public ChannelPoint getStart() {
        return null;
    }

    @Override
    public ChannelPoint getEnd() {
        return null;
    }
}

Dazu das Interface Check:
Java:
public interface Check {
    boolean execute();
    String getCheckName();
    ChannelPoint getStart();
    ChannelPoint getEnd();
}

Nur wie müsste ich denn hier jetzt an der gekennzeichneten Quellcode-Stelle den Stream schreiben? Lösen könnte ich das über eine ForEach und if Kaskade, denke aber, dass soetwas ja prädestiniert für Streams ist und damit dann auch deutlich schöner zu lesen ist.
 
H

httpdigest

Top Contributor
Das Problem hierbei ist, dass du ja nicht einfach deine Temperaturenliste filtern möchtest, sondern einen Zustand aufrechterhalten willst. Wenn wir mal einfache Zahlen als Beispiel nehmen, willst du ja z.B. nicht aus der Liste [1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5] einfach alle Zahlen zwischen 2 und 5 haben, sondern den ersten Bereich, in dem sich die Zahlen zwischen 2 und 5 bewegen.
Hierfür sind Streams nicht wirklich elegant.
Eine Lösung, die mir da einfallen würde, die einfach ganz generisch den ersten Bereich (die Indizes) aus einer Liste von T <: Comparable liefert, der in einem definierten Bereich min <= max liegt, wäre z.B.:
Java:
public class Ranges {
    public static <T extends Comparable<T>> int[] findIndicesOfFirstRangeBetweenMinMax(
            T min, T max, java.util.List<T> s) {
        return java.util.stream.IntStream.
         range(0, s.size())
        .dropWhile(i -> s.get(i).compareTo(min) < 0)
        .takeWhile(i -> s.get(i).compareTo(min) >= 0 && s.get(i).compareTo(max) <= 0)
        .boxed()
        .reduce((int[]) null,
                (pair, e) ->
                    pair == null
                    ? new int[] {e, e}
                    : new int[] {pair[0], e},
                (a, b) -> null);
    }
    public static void main(String[] args) {
        System.out.println(java.util.Arrays.toString(
                findIndicesOfFirstRangeBetweenMinMax(
                        3, 6,
                        java.util.List.of(1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9))));
    }
}
 
B

Bela B.

Aktives Mitglied
Danke @httpdigest , ich schaue mir deinen Vorschlag mal im Detail an. Muss mir mal ein gutes Tutorial bezüglich Streams suchen und die Doku durchackern, denn mir wäre deine Lösung so auch nie eingefallen (kenne so gut wie keine Methoden, die du da aufrust, also z.B. dropWhile, boxed, ...).

Wenn ihr da Vorschläge für Tutorials habt, gerne her damit.
 
temi

temi

Top Contributor
Wenn ihr da Vorschläge für Tutorials habt, gerne her damit.

Schau doch einfach in die Doku: https://docs.oracle.com/javase/9/docs/api/java/util/stream/Stream.html
und experimentiere etwas damit herum.

Ich hatte früher auch immer ziemlich Respekt vor der Doku, aber sie ist einfach super, da man über die Links sehr schnell zwischen den einzelnen Typen (Rückgabetypen oder Parametertypen) und Hinweisen hin- und herspringen kann.

Sobald man sich daran gewöhnt hat damit zu arbeiten, geht der erste Blick immer dahin.
 
Zuletzt bearbeitet:
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Ich persönlich würde dafür keine Streams nutzen, das lässt sich ohne deutlich schöner und eleganter lösen. Etwas so in die Richtung würde mir vorschweben:

Java:
import java.util.*;
import java.util.function.*;


public class IntervalCollector<T> {

    private final Predicate<T> check;

    private final List<Deque<T>> sets = new ArrayList<>();

    private Deque<T> current = null;


    public IntervalCollector(final Predicate<T> check) {
        this.check = check;
    }


    public void add(T point) {
        if (!check.test(point)) {
            current = null;
            return;
        }

        if (current == null) {
            current = new ArrayDeque<>();
            sets.add(current);
        }

        current.add(point);
    }

    public static void main(String[] args) {
        var ints = Arrays.asList(1, 2, 1, 6, 2, 2, 5, 7, 8, 2, 6, 2, 4, 7, 8, 4, 2);
        var collector = new IntervalCollector<Integer>((i) -> i > 2 && i < 8);
        ints.forEach(collector::add);
        System.out.println(collector.sets);
    }

}
 
B

Bela B.

Aktives Mitglied
Danke auch dir @mrBrown

Da ich in Streams wie gesagt noch nicht fit bin, fehlt mir auch noch der Blick dafür, wo sie Sinn machen.
Nach meinen ersten Gehversuchen damit, erschien mir mein Fall halt mit Streams elegant lösbar, ich weiß/wusste nur nicht wie.

Deque kannte ich bisher auch nicht. Ich denke, ich muss mir da nochmal einiges draufpacken, was die "neueren" Features betrifft.
 
B

Bela B.

Aktives Mitglied
Muss jetzt nochmal blöd nachfragen, gehe gerade den Code von @mrBrown durch, verstehe aber ehrlich gesagt die Zeile private final List<Deque<T>> sets = new ArrayList<>(); nicht.

Warum ist denn hier eine List in einer List (Deque ist ja quasi auch sowas wie eine Liste und laut mrBrown und auch meinem Verständnis, brauche ich kein Deque).

Wofür genau brauche ich hier current und sets als List?
 
mrBrown

mrBrown

Super-Moderator
Mitarbeiter
Muss jetzt nochmal blöd nachfragen, gehe gerade den Code von @mrBrown durch, verstehe aber ehrlich gesagt die Zeile private final List<Deque<T>> sets = new ArrayList<>(); nicht.

Warum ist denn hier eine List in einer List (Deque ist ja quasi auch sowas wie eine Liste und laut mrBrown und auch meinem Verständnis, brauche ich kein Deque).

Wofür genau brauche ich hier current und sets als List?
Der Code sucht nicht nur die erste, sondern alle Sublisten, für die die Bedingung zutrifft – deine Anforderungen klangen zumindest danach.

Für [2,3,4,3,2,5,6,5,2] und der Bedingen 2 < x < 7 würden [3,4,3] und [5,6,5] gefunden werden, daher eine Liste von Listen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Verwirrung bei Streams aus primitiven Arrays Java Basics - Anfänger-Themen 2
S Streams - Abfrage absteigend sortieren Java Basics - Anfänger-Themen 11
S Streams - kleinstes Element finden Java Basics - Anfänger-Themen 4
J String Array zu Map<Character, List<Character>> mit Streams Java Basics - Anfänger-Themen 1
Kirby.exe Fehlende Int Werte aus Array mit streams finden Java Basics - Anfänger-Themen 19
W Eclipse Autoformatierung für Streams ändern ? Java Basics - Anfänger-Themen 1
S Lambda Ausdrücke Streams Java Basics - Anfänger-Themen 6
I Streams Java Basics - Anfänger-Themen 12
N Frage zu Streams Java Basics - Anfänger-Themen 3
U Input/Output Unterschiede Streams Java Basics - Anfänger-Themen 2
X Streams und Ausgabe - lässt sich das einfacher schreiben oder schöner schreiben? Java Basics - Anfänger-Themen 5
C system.out.printf mit streams benutzen Java Basics - Anfänger-Themen 7
C Methoden Sortieren mit Streams: Auf- und absteigend Java Basics - Anfänger-Themen 2
O Streams und die flush Methode Java Basics - Anfänger-Themen 3
P InputStream eines Musik-Streams abspielen Java Basics - Anfänger-Themen 2
M Input/Output Streams Java Basics - Anfänger-Themen 5
T Klassen wie funktionieren Streams, warum bekomme ich int zurück? Java Basics - Anfänger-Themen 2
J Java 8 Streams - Frage zu "reduce" Java Basics - Anfänger-Themen 6
Sogomn Input/Output Reader, Writer und Streams Java Basics - Anfänger-Themen 6
T Fehler mit Streams! Java Basics - Anfänger-Themen 2
T Input/Output Object Streams Java Basics - Anfänger-Themen 6
J Per I/O Streams in LinkedList oder ArrayList schreiben/lesen Java Basics - Anfänger-Themen 6
I Java Streams Java Basics - Anfänger-Themen 6
R Streams for runaways Java Basics - Anfänger-Themen 5
RySa Input/Output Datei kann nicht gelöscht werden, obwohl Streams geschlossen sind. Java Basics - Anfänger-Themen 2
D Input/Output streams und readLine() Java Basics - Anfänger-Themen 3
firefexx Input/Output close() bei mehreren Streams Java Basics - Anfänger-Themen 5
M Frage zu Streams Java Basics - Anfänger-Themen 9
C try finally - Streams schließen Java Basics - Anfänger-Themen 7
M Streams und Sockets Java Basics - Anfänger-Themen 3
M file löschen, streams evtl noch offen Java Basics - Anfänger-Themen 7
G Character-orientierte File-Streams mit der Klasse FileReader Java Basics - Anfänger-Themen 5
S Piped Streams / Threads Java Basics - Anfänger-Themen 6
H Frage zu Byte-Streams Java Basics - Anfänger-Themen 2
P Streams mit Sockets Java Basics - Anfänger-Themen 7
V Performance Lesen und Schreiben aus/in Streams Java Basics - Anfänger-Themen 4
C RandomAccessFile vs. Streams Java Basics - Anfänger-Themen 5
M Probleme mit den Streams Java Basics - Anfänger-Themen 2
G streams schließen Java Basics - Anfänger-Themen 2
P Fragen zu STreams Java Basics - Anfänger-Themen 5
M Streams Java Basics - Anfänger-Themen 4
H Streams etc. erster Versuch Zeilen aus einer Datei zu lesen Java Basics - Anfänger-Themen 6
? Streams Java Basics - Anfänger-Themen 2
R RandomAccessFile mit anderen Streams verbinden Java Basics - Anfänger-Themen 5
G Rekursionsaufgabe mit Streams Java Basics - Anfänger-Themen 5
J Problem mit Streams Java Basics - Anfänger-Themen 15
L Streams und Reader/Writer Java Basics - Anfänger-Themen 8
K Frage zu SdtOut streams bzw. Socket Programmierung Java Basics - Anfänger-Themen 3
M Streams, read and write Java Basics - Anfänger-Themen 2
M Streams Java Basics - Anfänger-Themen 2
B Streams wollen scheinbar nicht schließen Java Basics - Anfänger-Themen 6
S Umwandlung eines Character-Streams in ein Image Java Basics - Anfänger-Themen 17
E Probleme mit Streams Java Basics - Anfänger-Themen 3
J Hilfestellung zu Hochschulaufgaben Java Basics - Anfänger-Themen 19
J Suche Hilfestellung Java Basics - Anfänger-Themen 10
A Hilfestellung zur Implementierung des Gaußsches Eliminationsverfahren Java Basics - Anfänger-Themen 4
R Hilfestellung bei Iteratorimplementierung Java Basics - Anfänger-Themen 4
P Hilfestellung bei einer Aufgabe Java Basics - Anfänger-Themen 3
S Interpreter-Fehler Hilfestellung bei einer NullPointerException Java Basics - Anfänger-Themen 1
A Hilfestellung zum Thema Persistenz Java Basics - Anfänger-Themen 12
N BinärBaum Hilfestellung Java Basics - Anfänger-Themen 8
G hilfestellung bei Array Java Basics - Anfänger-Themen 5
M Hilfestellung zur schularbeit Java Basics - Anfänger-Themen 17
B Java Bean, JSP, Komplexer Datentyp Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Anzeige

Neue Themen


Oben