2016-10-07 1 views
10

Gibt es einen eleganteren Weg, dies in Java 8 praktisch zu erreichen?Java 8 collect() nur isPresent() Optionale Werte

list.stream() 
    .map(e -> myclass.returnsOptional(e)) 
    .filter(Optional::isPresent) 
    .map(Optional::get) 
    .collect(Collectors.toList()); 

Ich rede über filter(Optional::isPresent) von map(Optional::get) gefolgt, möchte ich nur Optional Ergebnisse in einer Liste elegant sammeln, die einen Wert haben.

+7

Es sieht für mich in Ordnung. Ich bin mir nicht sicher, was dir daran nicht gefällt. – khelwood

+0

Wenn all Ihre Optionals ein Ergebnis haben, ist dies kein Optional mehr. Anstatt ein optionales Element zurückzugeben und zu prüfen, ob isPresent Nullen und Filter zurückgeben kann, ist es einen Schritt kürzer. 'list.stream(). map (e -> myclass.returnsObjectOrNull (e)). filter (Objekte :: nonNull) .collect (Collectors.toList())' – alfasin

+2

.map (o -> o.map (Stream: : of). orElseGet (Stream :: leer)) oder sehen Sie die Antworten hier: http://StackOverflow.com/Questions/22725537/using-Java-8S-optional-with-streamflatmap – hasan

Antwort

-1

Nicht sicher, ob es so anders ist, aber Sie könnten nur basierend auf Ihrem optionalen filtern, anstatt die optionale und filtern als nächstes. So ähnlich?

list.stream() 
    .filter(e -> myclass.returnsOptional(e).isPresent()) 
    .collect(Collectors.toList()); 

Hinweis: Dies funktioniert nur, wenn returnsOptional den gleichen Objekttyp wie Ihre ursprüngliche Liste Elementtypen zurückgibt.

+0

Das wird nicht die gleiche Liste erzeugen wie die, die das OP produziert. – khelwood

+0

hmm warum nicht? –

+0

Da 'list' vom Typ say' Foo' ist und 'myclass.returnsOptional (Foo)' 'return' Optional '. Am Ende brauche ich 'List ' und Sie produzieren 'List ' –

1

In Ihrem Fall können Sie eine flatMap anstelle von Kombinationen von mapfilter und wieder map verwenden. Um dies zu tun, ist es besser, eine separate Funktion zum Erstellen eines Streams zu definieren: public private static Stream<Integer> createStream(String e), um mehrere Zeilen Code in Lambda-Ausdruck nicht zu haben.

Bitte beachten Sie meine volle Demo Beispiel:

public class Demo{ 
    public static void main(String[] args) { 
     List<String> list = Arrays.asList("1", "2", "Hi Stack!", "not", "5"); 
     List<Integer> newList = list.stream() 
       .flatMap(Demo::createStream) 
       .collect(Collectors.toList()); 
     System.out.println(newList); 
    } 

    public static Stream<Integer> createStream(String e) { 
     Optional<Integer> opt = MyClass.returnsOptional(e); 
     return opt.isPresent() ? Stream.of(opt.get()) : Stream.empty(); 
    } 
} 


class MyClass { 
    public static Optional<Integer> returnsOptional(String e) { 
     try { 
      return Optional.of(Integer.valueOf(e)); 
     } catch (NumberFormatException ex) { 
      return Optional.empty(); 
     } 
    } 
} 

bei returnsOptional nicht statisch sein können benötigen Sie „Pfeil“ verwenden Ausdruck anstelle von „Methode Referenz“