Forum: PC-Programmierung Java: .map().flatMap).map().collect()


von Vili (Gast)


Lesenswert?

Was ergibt am Ende das untere Konstrukt?
1
.map().flatMap).map()collect()

Code Beispiel:
1
SortedSet<String> signalNames = new TreeSet<>();
2
3
signalNames.addAll
4
(varList.stream().map(variant::getSignals)
5
                 .flatMap(SortedSet<Signal>::stream)
6
                 .map(Signal::getSignalName)
7
                 .collect(Collectors.toList()));

In den einzelnen Typen sind ja Methodenaufrufe da. Gemeint ist z.B. dass 
variant::getSignals ein Methodenaufruf ist.

Was ich nicht verstehe, welchen Typ vom Parameter kriegt jetzt die 
Methode addAll?

von Dirk K. (merciless)


Lesenswert?

Vili schrieb:
> Was ergibt am Ende das untere Konstrukt?
>
>
1
.map().flatMap).map()collect()
Dieser Code zeigt wieder mal, warum ich Java verabscheue.
In jedem Java-Code, in den ich reingeschaut habe, waren
solche Konstrukte zu finden.

> Was ich nicht verstehe, welchen Typ vom Parameter kriegt jetzt die
> Methode addAll?
Ich nehme an, collect() liefert Liste (oder einen
adäquaten Container) zurück.

merciless

von was (Gast)


Lesenswert?

Vili schrieb:
> Was ich nicht verstehe, welchen Typ vom Parameter kriegt jetzt die
> Methode addAll?

Was auch immer .collect() liefert

von Matthias (Gast)


Lesenswert?

Dirk K. schrieb:
> Dieser Code zeigt wieder mal, warum ich Java verabscheue.
> In jedem Java-Code, in den ich reingeschaut habe, waren
> solche Konstrukte zu finden.

Ich finde das prima zu lesen. Vermutlich besser, als die 3 mal so lange 
ausformulierte Variante mit Schleife und temporären Hilfscollections. 
Wenn man das vernünftig formatiert, entspricht jede Zeile in so einer 
Kette einer Operation auf der Collection, die wieder eine irgendwie 
geartete Collection zurückgibt. Kommentare fressen natürlich kein Brot 
und wären nett, um die Intention der jeweiligen Einzeloperation nochmal 
zu zeigen.

Ich habe das letzte Mal mit Java entwickelt, als es das Kram noch nicht 
gab. Trotzdem denke ich, auf einen Blick ein halbwegs gutes Verständnis 
zu haben, was dort passieren soll...

von Christian F. (feuerwerk)


Lesenswert?

Hi zusammen

Wie Dirk bereits gesagt hat entspricht jede Codezeile einer Operation:

1) Für jedes Element (var) in varList tue....
.stream()

2) Rufe die Liste der Signale von var ab
.map(variant::getSignals)

3) Für jedes Element (signal) in der Signalliste tue...
.flatMap(SortedSet<Signal>::stream)

4) Rufe des Signalnamen von Signal ab
.map(Signal::getSignalName)

5) Sammle alles in einer Liste (vom Typ List<String>) und gib diese 
zurück
.collect(Collectors.toList()))

Hier mal ein Beispiel wie das ganze ausgeschrieben aussehen würde:
1
SortedSet<String> signalNames = new TreeSet<>();
2
List<String> temp = new ArrayList<>();
3
4
for (variant var : varList)
5
{
6
   for (Signal signal : var.getSignals())
7
   {
8
      temp.add(signal.getSignalName());
9
   }
10
}
11
12
signalNames.addAll(temp);

Gruß
Christian

von Markus (Gast)


Lesenswert?

Christian F. schrieb:
> Wie Dirk bereits gesagt hat entspricht jede Codezeile einer Operation:

Meine Programmierkenntnisse beschränken sich auf Python und VBA, aber 
ich war davon ausgegangen, daß das ganze von rechts nach links 
abgearbeitet wird, also collect liefert was an map, was wiederum an 
flatmap übergeben wird usw. Auf das von Christian F. geschilderte 
Verhalten wäre ich nie gekommen...

von cppbert (Gast)


Lesenswert?

Markus schrieb:
> Christian F. schrieb:
>> Wie Dirk bereits gesagt hat entspricht jede Codezeile einer Operation:
>
> Meine Programmierkenntnisse beschränken sich auf Python und VBA, aber
> ich war davon ausgegangen, daß das ganze von rechts nach links
> abgearbeitet wird, also collect liefert was an map, was wiederum an
> flatmap übergeben wird usw. Auf das von Christian F. geschilderte
> Verhalten wäre ich nie gekommen...

Das Verhalten ist genau so auch in Python und VBA

von Sascha (Gast)


Lesenswert?

Obwohl man das mit addAll in dem Fall nicht macht, da collect direkt ein 
TreeSet zurückgeben kann.

Also eher:

SortedSet<String> signalNames = varList.stream()
    .map(variant::getSignals)
    .flatMap(Collections::stream)
    .map(Signal::getSignalName)
    .collect(Collectors.toCollection(TreeSet::new)));

von Sascha (Gast)


Lesenswert?

Achso, du solltest dir auch überlegen, ob es wirklich eine immer 
sortiere Menge sein muss. TreeSet ist halt langsam beim hinzufügen, 
löschen von Elementen.

Wenn du die Liste nur 1x erzeugst und dann nicht mehr änderst wäre 
folgendes performanter.

List<String> signalNames = varList.stream()
    .map(variant::getSignals)
    .flatMap(Collections::stream)
    .map(Signal::getSignalName)
    .distinct() // Filtert doppelte Einträge aus
    .sorted() // Sortiert anschließend nach der natürlichen Ordnung
    .collect(Collectors.toList()));

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.