Proudy v Java 8

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:

Napsat komentář