Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Brauche Hilfe bei "Funktionale Programmierung "

8 views
Skip to first unread message

Marco Moock

unread,
Nov 19, 2022, 2:17:13 PM11/19/22
to
Am 19.11.2022 um 19:01:13 Uhr schrieb Ralf Schneider:

> seit ein paar Tagen arbeite ich mich in die Funktionale
> Programmierung mit Java ein und stehe vor einer unlösbaren Aufgabe.
> Nach langer Suche im Internet mit vielen Beispielen und der
> Betrachtung der APIs komme ich nicht weiter.

Ich denke, dass das in de.comp.lang.java besser aufgehoben ist, daher
Follow-Up.

Zudem solltest du die Fehlermeldung im exakten Wortlaut posten.

Christian Garbs

unread,
Nov 19, 2022, 3:44:53 PM11/19/22
to
Mahlzeit!

Ralf Schneider <schne...@freenet.de> wrote:

> Stream<BigInteger> liste = listeEins.stream();
> Stream<String> zeichen = liste.mapToObj(String::new);
>
> Da ich mit Eclipse arbeite, werde ich auf viele Fehler aufmerksam gemacht.
> Leider auch bei diesem Konstrukt. Es wird nicht kompiliert. Meldung ist,
> dass die Methode mapToObj nicht angewandt werden kann.

mapToObj() ist eine Methode aus IntStream, LongStream und
DoubleStream. Die heißt so, weil man damit die gewrappten Primitive
in beliebige Objekte mappen kann.

Du arbeitest aber mit der Klasse Stream. Die arbeitet bereits mit
beliebigen Objekten (in Deinem Fall BigInteger), daher heißt die
Methode dort einfach nur map().

Mit liste.map(String::new) sollte es also klappen.


Das hat aber nichts mit Linux zu tun, die Java-Newsgruppe ist dort
drüben *zeig*, ich leite mal weiter.

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
Wer später bremst, fährt länger schnell.

Ralf Schneider

unread,
Nov 19, 2022, 6:17:48 PM11/19/22
to
Am Sat, 19 Nov 2022 20:44:49 -0000 (UTC) schrieb Christian Garbs:

> Mit liste.map(String::new) sollte es also klappen.
>
>
> Das hat aber nichts mit Linux zu tun, die Java-Newsgruppe ist dort
> drüben *zeig*, ich leite mal weiter.

Du hast recht. Ich habe mich in die falsche Gruppe verirrt. Hier ist es
wohl richtiger.

Deine Version erzeugt den Fehler "The method map(String::new) is undefined
for the type List<BigInteger>", geht also auch nicht wie gewünscht. Auch
mit dem Stream geht map nicht, da es ein Primitivum zurückliefert, wenn
ich der Beschreibung in der API glauben darf.

Ich versuche ein Objekt zu erzeugen und mit mapToObj() ein solches weiter
zu leiten, was ich aber auch nicht hin bekommen habe. Das ist es, was mich
wundert.

Ich habe folgende Methode erstellt:

public List<ZahlenPaar> mischeZahlenListen(List<BigInteger> listeInnen,
List<BigInteger> listeAussen){

// Darin eine Funktion zur Erstellung eins Objektes:
BiFunction<BigInteger, BigInteger, ZahlenPaar> erstelleObjekt = (o,i) ->
{ ZahlenPaar zp = new ZahlenPaar(i, o);
return zp;
};

List<ZahlenPaar> gemischtePaare = listeAussen.stream()
.map(first -> {
ZahlenPaar attribute = listeInnen.stream()
.filter(second -> second != BigInteger.ZERO)
.mapToObj(second -> { ZahlenPaar z =
erstelleObjekt.apply(first, second);
return z;
});}).collect(Collectors.toList());

return gemischtePaare;
}

Ich will zwei Listen (List<BigInteger> ) in einer geschachtelten Schleife
so miteinander kombinieren, dass alle Elemente der einen Liste mit allen
Elementen der anderen Liste paarig in je ein Objekt des Typs
List<ZahlenPaar> umgewandelt werden.(1,2,3 und 4,5,6 sollen werden 1;4,
1;5, 1;6, 2;4 usw. bis zum neunten.)

Ich versuche schon Stunden, ohne einen funktionierenden Ansatz ans Laufen
zu bekommen.

Sieht jemand ein Lösung ?

Gruß
Ralf






Ralf Schneider

unread,
Nov 20, 2022, 4:30:07 PM11/20/22
to
Am 20 Nov 2022 11:13:40 GMT schrieb Stefan Ram:

> Ralf Schneider <schne...@freenet.de> writes:
>>Sieht jemand ein Lösung ?
>
> public final class Main { public static void main( final
> java.lang.String[] args )
> { java.util.List< java.math.BigInteger >list =
> new java.util.ArrayList< java.math.BigInteger >();
> list.add(
> java.math.BigInteger.valueOf( 1 ));
> list.add( java.math.BigInteger.valueOf( 2 ));
Das ist dieselbe Liste, die dort erweitert wird, also nicht die erhoffte
Lösung zwei Listen zu einem Objekt zusammen zu fügen.

> java.util.stream.Stream< java.lang.String >stringStream = \
> list.stream().map( java.math.BigInteger::toString );
Wie ich schrieb, liefert map kein Objekt, sondern ein Primitivum.

> stringStream.forEach( java.lang.System.out::println ); }}
Wo erhalte ich hier das Objekt ? Nach forEach kommt kein Stream mehr raus.

Tut mir leid, aber ich erkenne hier keine Lösung, die meine Frage
beantwortet.

Leider ist das in der Theorie und den vielen Beispielen im Internet alles
wunderbar und aufgeschrieben, nur funktioniert das Kompilieren nicht.

Gruß
Ralf

Ralf Schneider

unread,
Nov 20, 2022, 4:31:27 PM11/20/22
to
Am 20 Nov 2022 11:34:35 GMT schrieb Stefan Ram:

> Und hier das entsprechende Python-Programm:

Ich bin bei Java.

Gruß
Ralf

Ralf Schneider

unread,
Nov 20, 2022, 4:33:31 PM11/20/22
to
Am 20 Nov 2022 12:09:46 GMT schrieb Stefan Ram:

> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>>java.util.stream.Stream< java.lang.String >stringStream = \
>
> Der obige inverse Schrägstrich ist ein Fehler und sollte aus dem
> Programm entfernt werden!

Es handelt sich um einen Zeilenumbruch. Ich hatte so einen Verdacht.

Gruß
Ralf

Patrick Roemer

unread,
Nov 21, 2022, 4:10:55 AM11/21/22
to
Responding to Ralf Schneider:
> public List<ZahlenPaar> mischeZahlenListen(List<BigInteger> listeInnen,
> List<BigInteger> listeAussen){
>
> // Darin eine Funktion zur Erstellung eins Objektes:
> BiFunction<BigInteger, BigInteger, ZahlenPaar> erstelleObjekt = (o,i) ->
> { ZahlenPaar zp = new ZahlenPaar(i, o);
> return zp;
> };
>
> List<ZahlenPaar> gemischtePaare = listeAussen.stream()
> .map(first -> {
> ZahlenPaar attribute = listeInnen.stream()
> .filter(second -> second != BigInteger.ZERO)
> .mapToObj(second -> { ZahlenPaar z =
> erstelleObjekt.apply(first, second);
> return z;
> });}).collect(Collectors.toList());
>
> return gemischtePaare;
> }
>
> Ich will zwei Listen (List<BigInteger> ) in einer geschachtelten Schleife
> so miteinander kombinieren, dass alle Elemente der einen Liste mit allen
> Elementen der anderen Liste paarig in je ein Objekt des Typs
> List<ZahlenPaar> umgewandelt werden.(1,2,3 und 4,5,6 sollen werden 1;4,
> 1;5, 1;6, 2;4 usw. bis zum neunten.)

Disclaimer: Mein Java ist etwas angestaubt, kann durchaus sein, dass es
besser geht...

Wenn Du verschachtelt über zwei Streams #map() aufrufst, erhältst Du
auch ein verschachteltes Stream<Stream<...>>. Du wirst den Kombinator
#flatMap() benötigen.

Vergleiche die Signaturen:

<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<R> Stream<R> flatMap(
Function<? super T, ? extends Stream<? extends R>> mapper
);

https://www.baeldung.com/java-difference-map-and-flatmap

import java.math.*;
import java.util.*;
import java.util.stream.*;

static class Pair<A, B> {
// ...
}

private static <A, B> List<Pair<A, B>> combinations(
List<A> as, List<B> bs
) {
return
as.stream().flatMap(a ->
bs.stream().map(b ->
new Pair<A, B>(a, b)
)
)
.collect(Collectors.toList());
}

List<BigInteger> as =
Arrays.asList(1, 2, 3)
.stream()
.map(BigInteger::valueOf)
.collect(Collectors.toList());
List<BigInteger> bs =
Arrays.asList(4, 5, 6)
.stream()
.map(BigInteger::valueOf)
.collect(Collectors.toList());
System.out.println(combinations(as, bs));
// [(1, 4), (1, 5), (1, 6), (2, 4), ...]

Mit #mapMulti() kann man zum selben Ergebnis kommen, da sehe ich aber
konzeptuell überhaupt keinen Vorteil - #flatMap() ist generischer.

https://www.baeldung.com/java-mapmulti

Wenn Du eh schon Java machst und funktionale Aspekte einbringen willst,
fein. Wenn Du (auf der JVM) funktionale Programmierung lernen möchtest,
könnte Scala eine bessere Wahl sein. Nur zum Vergleich mal Scala-Versionen:

def combinations[A, B](as: List[A], bs: List[B]): List[(A, B)] =
as.flatMap(a => bs.map((a, _)))

def combinations[A, B](as: List[A], bs: List[B]): List[(A, B)] =
for { a <- as ; b <- bs } yield (a, b)

Ralf Schneider

unread,
Nov 21, 2022, 9:09:23 AM11/21/22
to
Am 21 Nov 2022 08:38:19 GMT schrieb Stefan Ram:


> . Dort steht gar nichts von "zwei Listen zu einem Objekt
> zusammenzufügen"!

Ich war schon etwas weiter:

public List<ZahlenPaar> mischeZahlenListen(List<BigInteger> listeInnen,
List<BigInteger> listeAussen){

// Darin eine Funktion zur Erstellung eins Objektes:
BiFunction<BigInteger, BigInteger, ZahlenPaar> erstelleObjekt = (o,i) ->
{ ZahlenPaar zp = new ZahlenPaar(i, o);
return zp;
};

List<ZahlenPaar> gemischtePaare = listeAussen.stream()
.map(first -> {
ZahlenPaar attribute = listeInnen.stream()
.filter(second -> second != BigInteger.ZERO)
.mapToObj(second -> { ZahlenPaar z =
erstelleObjekt.apply(first, second);
return z;
});}).collect(Collectors.toList());

return gemischtePaare;
}

Es handelt sich um eine spezielle Anwendung, zu der viele Leute im
Internet eine Äußerung gemacht haben. Deren Kode wurde aber wohl nicht
überprüft.

Gruß
Ralf


Ralf Schneider

unread,
Nov 21, 2022, 9:23:07 AM11/21/22
to

> Vergleiche die Signaturen:
>
> <R> Stream<R> map(Function<? super T, ? extends R> mapper); --- da war
ich einem Irrtum aufgesessen. Danke für das Zitat !

> <R> Stream<R> flatMap(
> Function<? super T, ? extends Stream<? extends R>> mapper

Das sehe ich mir an:

> private static <A, B> List<Pair<A, B>> combinations(
> List<A> as, List<B> bs
> ) {
> return
> as.stream().flatMap(a ->
> bs.stream().map(b ->
> new Pair<A, B>(a, b)
> )
> ) .collect(Collectors.toList());
> }

Der Rest ist nichts für mich.

Gruß
Ralf


Ralf Schneider

unread,
Nov 21, 2022, 9:25:34 AM11/21/22
to
Am 21 Nov 2022 09:19:52 GMT schrieb Stefan Ram:

> Mein Programm bezog sich also auf dieses OP.
Ist in Ordnung. Auch ich habe mich geirrt. Ich melde mich, wenn ich die
erhaltenen Beispiele getestet habe.

Gruß
Ralf

Ralf Schneider

unread,
Nov 21, 2022, 11:35:50 AM11/21/22
to
Am Mon, 21 Nov 2022 14:23:05 -0000 (UTC) schrieb Ralf Schneider:

Vielen Dank für die letzte Lösung ! Ich habe es angepasst und nun
funktioniert es wie gewünscht.


public List<ZahlenPaar> mischeZahlenListen(List<BigInteger> listeAussen,
List<BigInteger> listeInnen){

List<ZahlenPaar> gemischtePaare = listeAussen.stream().flatMap(
a -> listeInnen.stream().map(
b -> new ZahlenPaar(a, b)))
.collect(Collectors.toList());
return gemischtePaare;
}


flatMap war die Lösung und mein Irrtum mit map hat eine solche verhindert.

Wie gut, dass es das Usenet gibt. Danke an alle Kommentatoren !

Gruß
Ralf

Christian Garbs

unread,
Nov 25, 2022, 7:03:27 PM11/25/22
to
Mahlzeit!

Ralf Schneider <schne...@freenet.de> wrote:
> Am Sat, 19 Nov 2022 20:44:49 -0000 (UTC) schrieb Christian Garbs:
>
>> Mit liste.map(String::new) sollte es also klappen.

[…]

> Deine Version erzeugt den Fehler "The method map(String::new) is undefined
> for the type List<BigInteger>", geht also auch nicht wie gewünscht.

Das liegt daran, dass ich mich an Deiner Fehlerbeschreibung orientiert
und den Code nicht selber eingetippt habe - ich hatte nicht damit
gerechnet, dass das noch weitere Fehler drin sind.

Am besten die Fehlermeldungen des Compilers zusammen mit dem
Programmcode posten, die sind ja nicht ganz unnütz ;-)


Das konkrete Problem an meinem Code war, dass die Klasse String keinen
Konstruktor hat, der einen BigInteger akzeptiert.

Mögliche Lösungen dafür: statt map(String::new) entweder
map(BigInteger::toString) oder map(String::valueOf) benutzen.


Frage hier in die Runde: Bei sowas kann ich mich nie entscheiden.
Gibt es eine Präferenz, ob man foo.toString() oder
stattdessen String.valueOf(foo) nehmen sollte? Das ruft ja letztendlich
den gleichen Code auf.

Ein relevanter Unterschied ist das null-Handling ("null"
vs. NullPointerException), da kann man sich aussuchen, was einem
lieber wäre.

Gibt's darüberhinaus noch Unterschiede?
Oder fällt das unter "persönlicher Programmierstil"?

> Auch mit dem Stream geht map nicht, da es ein Primitivum
> zurückliefert, wenn ich der Beschreibung in der API glauben darf.

Stream<T>.map() liefert keinen primitiven Datentyp zurück, sondern
irgendein Objekt.

Primitive kommen aus den Methoden Stream<T>.mapToLong() und Konsorten.

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
Kronkorken:
Bestandteil bügelfreier Flaschen

Ralf Schneider

unread,
Nov 26, 2022, 1:55:10 PM11/26/22
to
Am Sat, 26 Nov 2022 00:03:24 -0000 (UTC) schrieb Christian Garbs:

> Stream<T>.map() liefert keinen primitiven Datentyp zurück, sondern
> irgendein Objekt.
War mein Fehler, wie schon geschrieben.
0 new messages