2016-04-21 19 views
3

Kann jemand mir erklären, warum die folgende nicht funktioniert:Java 8-Streams und einfache Typen

long la[] = new long[] {1,2,3}; 
Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet()); 

Wenn dies tut:

String la[] = new String[] {"1","2","3"}; 
Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet()); 

Erstere gibt einen Übersetzungsfehler, während die letztere nicht der Fall ist . Der Kompilierungsfehler ist so kryptisch (Eclipse), dass ich keinen Sinn daraus machen kann.

Antwort

2

Arrays.stream(la) führt die Methode public static LongStream stream(long[] array) aus, die eine LongStream erzeugt. Die LongStreammap Methode gibt eine LongStream zurück (d. H. Jedes long Element der Quelle LongStream wird einem long Element im Ziel LongStream zugeordnet). LongStream hat keine collect-Methode, die ein einzelnes Argument akzeptiert, weshalb collect(Collectors.toSet()) Kompilierung nicht besteht.

Es sollte funktionieren, wenn Sie mapToObj verwenden:

Set<Long> set = Arrays.stream(la).mapToObj(Long::valueOf).collect(Collectors.toSet()); 

Ihr zweites Schnipsel da hier arbeitet Arrays.stream erzeugt ein Stream einen Referenztyp (Stream<String>), deren map Verfahren erzeugt eine andere Stream einen Referenztyp (Stream<Long> in Ihrem Fall). Hier Stream hat eine collect Methode, die ein einzelnes Argument akzeptiert - collect(Collector<? super T, A, R> collector) - so collect(Collectors.toSet()) funktioniert.

+0

Dies wird das Problem lösen, aber es erklärt nicht, warum das erste Snippet kompiliert tho nicht Pfui. – Tunaki

+1

Kürzere: 'Arrays.stream (la) .boxed(). Sammeln (Collectors.toSet());' –

+0

'LongUnaryOperator o = Long :: valueOf' kompiliert fein. Das ist nicht das Problem. – Tunaki

2

Der Code sieht nur gleich aus. Das Verfahren Arrays.stream, die aufgerufen wird, ist tatsächlich anders in beiden Fällen:

Auf einem Stream<String> zurückgibt, können Sie map anrufen und geben einen Stream<R> basierend auf dem Rückgabetyp der Mapper. Aber auf LongStream, map wird immer eine LongStream zurückgeben, das ist die primitive Spezialisierung. Was passiert, ist, dass Long::valueOf Ihr long Element in ein Objekt verwandelt und dann wird es automatisch in eine long entpackt; effektiv tut der Anruf nichts außer einer Box/Unbox.

Dann erscheint das Problem auf dem collect Aufruf.

  • LongStream.collect erwartet 3 Argumente
  • Stream.collect ein 3 Argument Methode hat aber auch eine 1 Argument Methode, die diejenige, die Sie mit .collect(Collectors.toSet()); nennen ist.

So können Sie .collect(Collectors.toSet()); auf einem LongStream nicht aufrufen. Dies wird nicht kompiliert: es erwartet 3 Argumente.

Was Sie tun können, ist Aufruf mapToObj statt map auf den LongStream: Diese Methode deklariert eine Stream<R> (anstelle eine LongStream) aus dem Rückgabetyp des Mapper zurückzukehren. In diesem Fall ist der Mapper Long::valueOf, der ein Objekt zurückgibt, so dass es eine Stream<Long> zurückgibt.

Zur Erinnerung:

long la[] = new long[] {1,2,3}; 
    Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet()); 
//^--LongStream----^^---LongStream----^^  error 

    String la[] = new String[] {"1","2","3"}; 
    Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet()); 
//^-Stream<String>-^^--Stream<Long>--^^---- successful call -----^ 

    long la[] = new long[] {1,2,3}; 
    Arrays.stream(la).mapToObj(Long::valueOf).collect(Collectors.toSet()); 
//^--LongStream----^^-----Stream<Long>-----^^---- successful call -----^ 
+1

Warum wird dies abgelehnt? Nimm meine Erwiderung. –

+0

Danke für Ihre Antwort! – user1283068

0

zu beantworten, warum die erste nicht kompiliert, erzeugt dies ein LongStream:

Arrays.stream(la) 

Dieser jede long nimmt, schafft eine Long Wrapper, unboxes es dann zurück zu long. Strom ist immer noch ein LongStream:

.map(Long::valueOf) 

Dies geht einen einzigen Parameter zu LongStream.collect, die wegen LongStream.collect benötigt 3 Parameter fehlschlägt:

.collect(Collectors.toSet()) 

Sie müssen die map zu mapToObj ändern, wenn Sie das ändern wollen LongStream in eine Stream<Long> (oder LongStream.boxed())