Dieser Code funktioniert (im Javadoc aufgenommen):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
.map(i -> i.toString())
.collect(Collectors.joining(", "));
Dieser kann nicht kompiliert werden:
int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
.map((Integer i) -> i.toString())
.collect(Collectors.joining(", "));
IDEA sagt mir, dass ich einen "inkompatiblen Rückgabetyp String im Lambda-Ausdruck" habe.
Warum ? Und wie kann man das beheben?
java
functional-programming
java-8
java-stream
Denys Séguret
quelle
quelle
IntStream
undStream<Integer>
?IntStream
ist eine Stream-Spezialisierung für primitiveint
Werte. AStream<Integer>
ist nur ein Stream, derInteger
Objekte enthält.IntStream
ist ein Stream oder Primitive (Ints), währendSteram<Integer>
es sich um einen Stream von Objekten handelt. Primitive Streams verfügen aus Leistungsgründen über spezielle Methoden.IntStream.mapToObj
erwartet eineIntFunction
, eine Funktion, die einenint
Wert verbraucht, funktioniert daher.mapToObj((Integer i) -> i.toString())
nicht. Es wird sowieso nicht empfohlen, da es eine unnötige Konvertierung vonint
nach enthältInteger
. Im Gegensatz dazu.mapToObj(Integer::toString)
funktioniert es gut, da es diestatic
Methode aufruftInteger.toString(int)
. Beachten Sie, dass dies anders ist als das Aufrufen.map(Integer::toString)
von a,Stream<Integer>
da dieses nicht kompiliert werden kann, da es nicht eindeutig ist..map(Integer::toString)
von aStream<Integer>
ist als beides wirklich mehrdeutig.map(i->i.toString())
und.map(i->Integer.toString(i))
gültig. Aber es ist leicht lösbar mit.map(Object::toString)
.Arrays.stream(numbers)
Erstellt eineIntStream
unter der Haube und die Kartenoperation auf einerIntStream
erfordert eineIntUnaryOperator
(dh eine Funktionint -> int
). Die Zuordnungsfunktion, die Sie anwenden möchten, berücksichtigt diesen Vertrag und damit den Kompilierungsfehler nicht.Sie müssten
boxed()
vorher anrufen , um eine zu erhaltenStream<Integer>
(dies ist, wasArrays.asList(...).stream()
zurückkehrt). Rufenmap
Sie dann einfach an, wie Sie es im ersten Snippet getan haben.Beachten Sie, dass , wenn Sie brauchen ,
boxed()
gefolgt vonmap
Ihnen wahrscheinlich verwenden möchtenmapToObj
direkt.Der Vorteil ist, dass
mapToObj
nicht jederint
Wert einemInteger
Objekt zugeordnet werden muss. abhängig von der Mapping-Funktion wenden Sie natürlich an; also würde ich mich für diese Option entscheiden, die auch kürzer zu schreiben ist.quelle
Sie können einen Integer-Stream mit Arrays.stream (int []) erstellen, den Sie
mapToObj
wie aufrufen könnenmapToObj(Integer::toString)
.Hoffe das hilft..
quelle
Kein Boxen, AFAIK und keine Explosion kleiner Fäden, die dem Haufen hinzugefügt wurden:
quelle
Wenn der Zweck dieses Beispiels und dieser Frage darin besteht, herauszufinden, wie Zeichenfolgen einem Strom von Ints zugeordnet werden (z. B. Verwenden eines Stroms von Ints, um auf einen Index in einem Array von Zeichenfolgen zuzugreifen), können Sie auch Boxing und anschließend Casting verwenden ein int (das dann den Zugriff auf den Index des Arrays ermöglichen würde).
Der Aufruf von .boxed () konvertiert Ihren IntStream (einen Stream primitiver Ints) in einen Stream (einen Stream von Objekten - nämlich Integer-Objekte), der dann die Rückgabe eines Objekts (in diesem Fall eines String-Objekts) von akzeptiert dein Lambda. Hier ist es nur eine Zeichenfolgendarstellung der Zahl zu Demonstrationszwecken, aber es könnte genauso einfach (und praktischer) jedes Zeichenfolgenobjekt sein - wie das Element eines Zeichenfolgenarrays, wie zuvor erwähnt.
Ich dachte nur, ich würde eine andere Möglichkeit anbieten. Bei der Programmierung gibt es immer mehrere Möglichkeiten, eine Aufgabe zu erfüllen. Kennen Sie so viele wie möglich und wählen Sie dann diejenige aus, die für die jeweilige Aufgabe am besten geeignet ist. Beachten Sie dabei Leistungsprobleme, Intuitivität, Klarheit des Codes, Ihre Vorlieben im Codierungsstil und die Selbstdokumentation.
Viel Spaß beim Codieren!
quelle
int
nach seinem Wrapper-TypInteger
und entpacken ihn gleich danach.