2016-07-31 34 views
8

Próbuję poznać strumienie i napotkałem problem: Chcę uzyskać minimalną wartość listy i przypisać ją do zmiennej typu int. Do tego zrobiłem następujące:Strumienie Java 8 "ifPresent"

List<Integer> list = new ArrayList<>(); 
    list.add(1); 
    list.add(2); 
    list.add(3); 
    int smallest = list.stream().min(Integer::compareTo).get(); 
    System.out.println(smallest); 

Działa to dobrze, a ja dostać 1 wyniku. Problem polega na tym, że IDE daje ostrzeżenie, że Optional.get jest wywoływane przed sprawdzeniem pod kątem .isPresent. Aby ustalić, że użyłem nieco inną metodę ifPresent i próbowałem następujące:

int smallest = list.stream().min(Integer::compareTo).ifPresent(integer -> integer); 

Niestety to nie działa, ponieważ pojawia się ostrzeżenie: Bad return type in Lambda, Integer cannot be converted to void. Moje pytanie brzmi: jak w końcu mogę przypisać wartość min do zmienna int smallest WITH checking ifPresent?

+1

Najpierw musisz zrozumieć, dlaczego otrzymujesz wartość opcjonalną, a nie liczbę całkowitą: ponieważ strumień może być pusty, a zatem może nie być żadnej wartości minimalnej. Następnie musisz zdecydować, co chcesz uzyskać, jeśli strumień jest pusty. Następnie, gdy wiesz, czego chcesz, będziesz w stanie wybrać właściwy sposób uzyskania tego wyniku, patrząc na dokumentację Opcjonalnie. –

+1

'ifPresent' przyjmuje argument" Consumer "jako argument, który pobiera wartość wejściową i nie zwraca nic. –

Odpowiedz

6

Stream#min powrót Optional wyniku, ponieważ w ogólnym strumieniu może być pusty, więc nie może być minimalna wartość.

Optional<Integer> minimal = list.stream().min(Integer::compareTo); 

Aby uzyskać wartość z opcjonalnego trzeba mieć jakąś wartość awaryjnej

Integer absent = Integer.MIN_VALUE; 

Najłatwiej byłoby użyć orElse

Integer smallest = minimal.orElse(absent); 

trochę dłużej byłoby isPresent

Integer smallest = minimal.isPresent() ? minimal.get() : absent; 
+0

, więc metoda orElse zwraca typ liczb całkowitych, a nie opcjonalne, takie jak metoda .min? –

+1

tak, w tym przykładzie będzie to "Integer". Ogólnie "Opcjonalnie " może zawierać wartość dowolnego typu 'T', więc' lubElse' zwraca ten typ 'T' –

+0

Dziękuję bardzo! –

7

Oto jak ja to zrobię:

package lambdas; 

import java.util.ArrayList; 
import java.util.List; 

/** 
* Created by Michael 
* Creation date 7/31/2016. 
* @link https://stackoverflow.com/questions/38688119/java-8-streams-ifpresent 
*/ 
public class MinimumExample { 

    public static void main(String[] args) { 
     List<Integer> list = new ArrayList<>(); 
     int smallest = list.stream().min(Integer::compareTo).orElse(Integer.MIN_VALUE); 
     System.out.println(smallest); 
    } 
} 
+0

Jeśli metoda '.min' zwróci Opcjonalne, to metoda' .orElse' musi zwrócić liczbę całkowitą. Czy zatem '.orElse' wywołuje metodę' .get'? –

+0

Ten kod działa i działa.Zostało ono przesłane przez odpowiedź, którą przyjąłeś. Jakie jest Twoje pytanie? – duffymo

1

Metoda ifPresent przyjmuje jako parametr parametr Consumer<? super T>. Mówiąc prościej, powinno to być działanie bez stwierdzenia return. Możesz wydrukować wartość, jeśli jest obecna, jak na przykład IDEA, ale nie jest tak, jak w przypadku IDEA. Myślę, że po prostu trzeba zapisać wystąpienie Option<Integer> a następnie sprawdzić to isPresent:

Optional<Integer> o = list.stream().min(Integer::compareTo); 
if (o.isPresent()) { 
    smallest = o.get(); 
} 

Oczywiście, są bardziej wygodne sposoby z orElse:

smallest = o.orElse(Integer.MIN_VALUE); 

lub operatora potrójnego:

smallest = o.isPresent() ? o.get() : Integer.MIN_VALUE; 
Powiązane problemy