Proudové (stream) zpracovávání je novinka Javy 8. Cílem je zjednodušit operace nad posloupnostmi prvků. Umožňují zřetězení operací. Operace se dělí do dvou hlavních skupin:
- terminální (terminal) – touto operací je proud uzavřen
- neterminální (intermediate) – vytváří nový proud
Jak je vidět z popisu, neterminální operace lze za sebou řetězit, dokud se nezavolá operace terminální.
Nejpoužívanější operace jsou
forEach | terminální | všechny prvky proudu postupně odešle konzumentovi |
findFirst | terminální | vrátí první prvek pokud existuje |
collect | terminální | sesbírá elementy a vytvoří z nich návratovou strukturu |
map | neterminální | převede prvky na jiné |
filter | neterminální | filtruje podle zadaného predikátu (podmínky) |
sorted | neterminální | seřadí prvky |
Příklady použití.
Třída Person
class Person { private String name; private String surname; private Gender gender; private String country; private LocalDate dateOfBirth; public Person(String name, String surname, Gender gender, String country, LocalDate dateOfBirth) { this.name = name; this.surname = surname; this.gender = gender; this.country = country; this.dateOfBirth = dateOfBirth; } public String getName() { return name; } public String getSurname() { return surname; } public Gender getGender() { return gender; } public String getCountry() { return country; } public LocalDate getDateOfBirth() { return dateOfBirth; } } enum Gender { MALE, FEMALE }
Třída MyPerson
class MyPerson { private String name; private String surname; private int age; public MyPerson(String name, String surname, int age) { this.name = name; this.surname = surname; this.age = age; } public String getName() { return name; } public String getSurname() { return surname; } public int getAge() { return age; } @Override public String toString() { return name + " " + surname + ": " + age; } }
Vstupní seznam
List<Person> list = Arrays.asList( new Person("John", "Smith", Gender.MALE, "Germany", LocalDate.of(1983, 2, 13)), new Person("Marie", "Nováková", Gender.FEMALE, "Czech republic", LocalDate.of(1961, 10, 3)), new Person("František", "Koudelka", Gender.MALE, "Czech republic", LocalDate.of(2003, 5, 7)), new Person("Trung", "Nguien", Gender.MALE, "Vietnam", LocalDate.of(1995, 1, 28)), new Person("Jassie", "Cheyney", Gender.FEMALE, "Ireland", LocalDate.of(1987, 4, 19)) );
Metoda pro získání věku
private static int getAge(LocalDate date) { return (int) ChronoUnit.YEARS.between(date, LocalDate.now()); }
Přemapování objektů typu Person na typ MyPerson a vyfiltrování pouze těch, kteří mají 18 a více let.
List<MyPerson> myPersonList = list.stream() .map(person -> new MyPerson(person.getName(), person.getSurname(), getAge(person.getDateOfBirth()))) .filter(myPerson -> myPerson.getAge() >= 18) .collect(Collectors.toList()); System.out.println(Arrays.toString(myPersonList.toArray())); [John Smith: 34, Marie Nováková: 56, Trung Nguien: 23, Jassie Cheyney: 30]
Získání jmen (opět pomocí metody map).
List<String> names = list.stream() .map(person -> person.getName()) .collect(Collectors.toList()); System.out.println(Arrays.toString(names.toArray())); [John, Marie, František, Trung, Jassie]
Získání věku a jeho vzestupné seřazení.
List<Integer> years = list.stream() .map(person -> getAge(person.getDateOfBirth())) .sorted() .collect(Collectors.toList()); System.out.println(Arrays.toString(years.toArray())); [14, 23, 30, 34, 56]
Vybrání prvního věku (je seřazeno, takže vybere nejnižší věk v seznamu).
Optional<Integer> first = list.stream() .map(person -> getAge(person.getDateOfBirth())) .sorted() .findFirst(); System.out.println(first.orElseThrow(() -> new IllegalStateException("list was empty"))); 14
Vytvoření seznamu objektů typu MyPerson, kteří mají 18 a více let, seřazených od nejvyššího věku po nejnižší.
List<MyPerson> myPersonListSortedDesc = list.stream() .map(person -> new MyPerson(person.getName(), person.getSurname(), getAge(person.getDateOfBirth()))) .filter(myPerson -> myPerson.getAge() >= 18) .sorted((o1, o2) -> Integer.compare(o2.getAge(), o1.getAge())) .collect(Collectors.toList()); System.out.println(Arrays.toString(myPersonListSortedDesc.toArray())); [Marie Nováková: 56, John Smith: 34, Jassie Cheyney: 30, Trung Nguien: 23]
Zdroje: