JetBrains Academy: Stream pipelines - Kamil-Jankowski/Learning-JAVA GitHub Wiki
The sum of odd numbers:
Write a method for calculating the sum of odd numbers in the given interval (inclusively) using Stream API.
/**
* The method calculates the sum of odd numbers in the given range
*
* @param start of a range, start >= 0
* @param end of a range (inclusive), end >= start
*
* @return sum of odd numbers
*/
public static long sumOfOddNumbersInRange(long start, long end) {
return LongStream.rangeClosed(start, end)
.filter(num -> num % 2 != 0)
.reduce(0, (sum, number) -> sum + number);
}
The general number of employees:
You have two classes: Employee (name: String, salary: Long) and Department (name: String, code: String, employees: List). Both classes have getters for all fields with the corresponding names (getName(), getSalary(), getEmployees() and so on).
Write a method using Stream API that calculates the general number of employees with salary >= threshold for all departments whose code starts with string "111-" (without ""). Perhaps, flatMap method can help you to implement it.
/**
* Calculates the number of employees with salary >= threshold (only for 111- departments)
*
* @param departments are list of departments
* @param threshold is lower edge of salary
*
* @return the number of employees
*/
public static long calcNumberOfEmployees(List<Department> departments, long threshold) {
return departments.stream()
.filter(department -> department.getCode().startsWith("111-"))
.flatMap(departament -> departament.getEmployees().stream())
.filter(employee -> employee.getSalary() >= threshold)
.count();
}
The total sum of canceled transactions:
You have two classes:
- Transaction: uuid: String, state: State (CANCELED, FINISHED, PROCESSING), sum: Long, created: Date
- Account: number: String, balance: Long, transactions: List
Both classes have getters for all fields with the corresponding names (getState(), getSum(), getTransactions() and so on).
Write a method using Stream API that calculates the total sum of canceled transactions for all non-empty accounts (balance > 0). Perhaps, flatMap method can help you to implement it.
/**
* Calculates the general sum of canceled transactions for all non empty accounts in the list
*/
public static long calcSumOfCanceledTransOnNonEmptyAccounts(List<Account> accounts) {
return accounts.stream()
.filter(account -> account.getBalance() > 0)
.flatMap(account -> account.getTransactions().stream())
.filter(transaction -> transaction.getState().equals(State.CANCELED))
.map(transaction -> transaction.getSum())
.mapToLong(x -> x)
.sum();
}
The ten most frequent words:
Write a program that reads a text (in the UTF-8) from the standard input. The program must count the frequency of words in the text and print the 10 most frequent words.
A word is a sequence of characters consisting only of digits and letters. For example, the string "Functions bring happiness!" has three words: "Functions", "brings", "happiness".
The counting words should be case-insensitive, i.e. "Functions", "functions" and "FUNCTIONS" are the same word. Output words in the lower case.
If the text has less than 10 unique words, output as many as there are.
If some words in the text have the same frequency, order them lexicographically as well. For details, see here (https://en.wikipedia.org/wiki/Lexicographical_order).
import java.util.Arrays;
import java.util.Scanner;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Arrays.stream(scanner.nextLine().split("[\\p{Punct} \\s]+"))
.collect(Collectors.toMap(String::toLowerCase, occurrence -> 1, Integer::sum))
// key mapping, value mapping, merger function for the case when the same key occurs
.entrySet()
.stream()
.sorted((entry, nextEntry) -> nextEntry.getValue() == entry.getValue()
? entry.getKey().compareTo(nextEntry.getKey())
: nextEntry.getValue() - entry.getValue())
.limit(10)
.forEach(entry -> System.out.println(entry.getKey()));
}
}
Using streams many times:
Sometimes after mapping and filtering a stream, you need to use it more than one time. For example, find the maximum and count all the elements of a resulted sequence.
You need to implement a method that solves this problem. The method should save the stream and create a supplier, that can return this stream over and over again.
import java.util.function.*;
import java.util.stream.*;
class FunctionUtils {
public static <T> Supplier<Stream<T>> saveStream(Stream<T> stream) {
List<T> list = stream.collect(Collectors.toList());
return () -> list.stream();
}
}