Tipul Optional
O serie de operațiuni de agregare, precum min, max, reduce, returnează un obiect Optional<T>. Acest obiect înfășoară de fapt rezultatul operației. După efectuarea operației, cu ajutorul metodei get() a obiectului Optional, putem obține valoarea acestuia:
import java.util.Optional;
import java.util.ArrayList;
import java.util.Arrays;
public class Program {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.addAll(Arrays.asList(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9}));
Optional<Integer> min = numbers.stream().min(Integer::compare);
System.out.println(min.get()); // 1
}
}
Dar ce se întâmplă dacă fluxul nu conține date:
// lista numbers este goală
ArrayList<Integer> numbers = new ArrayList<Integer>();
Optional<Integer> min = numbers.stream().min(Integer::compare);
System.out.println(min.get()); // java.util.NoSuchElementException
În acest caz, programul va arunca excepția java.util.NoSuchElementException. Ce putem face pentru a evita aruncarea acestei excepții? Pentru aceasta, clasa Optional oferă o serie de metode.
Cea mai simplă modalitate de a evita o astfel de situație este verificarea preliminară a prezenței unei valori în Optional folosind metoda isPresent(). Aceasta returnează true dacă valoarea este prezentă în Optional și false dacă valoarea lipsește:
ArrayList<Integer> numbers = new ArrayList<Integer>();
Optional<Integer> min = numbers.stream().min(Integer::compare);
if (min.isPresent()) {
System.out.println(min.get());
}
Metoda orElse()
Metoda orElse() permite definirea unei valori alternative care va fi returnată dacă Optional nu conține nicio valoare din flux:
// lista goală
ArrayList<Integer> numbers = new ArrayList<Integer>();
Optional<Integer> min = numbers.stream().min(Integer::compare);
System.out.println(min.orElse(-1)); // -1
// lista ne-goală
numbers.addAll(Arrays.asList(new Integer[]{4, 5, 6, 7, 8, 9}));
min = numbers.stream().min(Integer::compare);
System.out.println(min.orElse(-1)); // 4
Metoda orElseGet()
Metoda orElseGet() permite setarea unei funcții care va returna valoarea implicită:
import java.util.Optional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
public class Program {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
Optional<Integer> min = numbers.stream().min(Integer::compare);
Random rnd = new Random();
System.out.println(min.orElseGet(() -> rnd.nextInt(100)));
}
}
În acest caz, valoarea returnată este generată folosind metoda nextInt a clasei Random, care returnează un număr aleatoriu.
Metodă orElseThrow
O altă metodă - orElseThrow permite generarea unei excepții dacă Optional nu conține nicio valoare:
ArrayList<Integer> numbers = new ArrayList<Integer>();
Optional<Integer> min = numbers.stream().min(Integer::compare);
// generare excepție IllegalStateException
System.out.println(min.orElseThrow(IllegalStateException::new));
Manipularea valorii obținute
Metoda ifPresent() definește acțiunile care se vor efectua cu valoarea din Optional, dacă aceasta există:
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.addAll(Arrays.asList(new Integer[]{4, 5, 6, 7, 8, 9}));
Optional<Integer> min = numbers.stream().min(Integer::compare);
min.ifPresent(v -> System.out.println(v)); // 4
În metoda ifPresent este transmisă o funcție care primește un parametru - valoarea din Optional. În acest caz, numărul minim obținut este afișat pe consolă. Dar dacă lista numbers ar fi fost goală și, prin urmare, Optional nu ar fi conținut nicio valoare, nu s-ar fi generat nicio eroare.
Metoda ifPresentOrElse() permite definirea unei logici alternative în cazul în care valoarea din Optional lipsește:
ArrayList<Integer> numbers = new ArrayList<Integer>();
Optional<Integer> min = numbers.stream().min(Integer::compare);
min.ifPresentOrElse(
v -> System.out.println(v),
() -> System.out.println("Valoare nu a fost găsită")
);
În metoda ifPresentOrElse sunt transmise două funcții. Prima prelucrează valoarea din Optional, dacă aceasta este prezentă. A doua funcție definește acțiunile care se vor efectua în cazul în care valoarea lipsește din Optional.