-
java stream is not Java I/O streams, streams are wrappers around a data source, allowing us to operate with that data source and making bulk processing convenient and fast.
A stream does not store data and, in that sense, is not a data structure. It also never modifies the underlying data source. -
Obtain a stream from an existing list:
private static List<Employee> empList = Arrays.asList(arrayOfEmps);
empList.stream();
- Use stream builder to obtain a stream
Stream.Builder<Employee> empStreamBuilder = Stream.builder();
empStreamBuilder.accept(arrayOfEmps[0]);
empStreamBuilder.accept(arrayOfEmps[1]);
empStreamBuilder.accept(arrayOfEmps[2]);
Stream<Employee> empStream = empStreamBuilder.build();
- Stream operation: forEach, map, collect, filter, findFirst, toArray, flatMap, peek
4.1) forEach: loop the stream elements
4.2) map: map() produces a new stream after applying a function to each element of the original stream. The new stream could be of different type.
@Test
public void whenMapIdToEmployees_thenGetEmployeeStream() {
Integer[] empIds = { 1, 2, 3 };
List<Employee> employees = Stream.of(empIds)
.map(employeeRepository::findById)
.collect(Collectors.toList());
assertEquals(employees.size(), empIds.length);
}
Each Integer is passed to the function employeeRepository::findById() – which returns the corresponding Employee object;
4.3) collect: collect(Collectors.toList()) repackaging elements to some data structures and applying some additional logic, concatenating them, etc.
4.4) filter: produces a new stream that contains elements of the original stream that pass a given test (specified by a Predicate).
4.5) findFirst: returns an Optional for the first entry in the stream.
4.6) toArray: Use collect() to get data out of the stream. But if we need to get an array out of the stream, we can simply use toArray():
4.7) flatMap: A stream can hold complex data structures like Stream<List<String>> to Stream<String>
@Test
public void whenFlatMapEmployeeNames_thenGetNameStream() {
List<List<String>> namesNested = Arrays.asList(
Arrays.asList("Jeff", "Bezos"),
Arrays.asList("Bill", "Gates"),
Arrays.asList("Mark", "Zuckerberg"));
List<String> namesFlatStream = namesNested.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
assertEquals(namesFlatStream.size(), namesNested.size() * 2);
}
4.8) peek: like forEach, but forEach is terminal option, but peek is an intermediate option.
@Test
public void whenIncrementSalaryUsingPeek_thenApplyNewSalary() {
Employee[] arrayOfEmps = {
new Employee(1, "Jeff Bezos", 100000.0),
new Employee(2, "Bill Gates", 200000.0),
new Employee(3, "Mark Zuckerberg", 300000.0)
};
List<Employee> empList = Arrays.asList(arrayOfEmps);
empList.stream()
.peek(e -> e.salaryIncrement(10.0))
.peek(System.out::println)
.collect(Collectors.toList());
assertThat(empList, contains(
hasProperty("salary", equalTo(110000.0)),
hasProperty("salary", equalTo(220000.0)),
hasProperty("salary", equalTo(330000.0))
));
}
- Why stream needed?
One of the most important characteristics of Java streams is that they allow for significant optimizations through lazy evaluations.
All intermediate operations are lazy, so they’re not executed until a result of a processing is actually needed.
eg.
@Test
public void whenFindFirst_thenGetFirstEmployeeInStream() {
Integer[] empIds = { 1, 2, 3, 4 };
Employee employee = Stream.of(empIds)
.map(employeeRepository::findById)
.filter(e -> e != null)
.filter(e -> e.getSalary() > 100000)
.findFirst()
.orElse(null);
assertEquals(employee.getSalary(), new Double(200000));
}
By lazy evaluation, stream performs the map and two filter operations, one element at a time. (comparing to direct array operation need 4 times)
-
Method type and pipelines
Terminal operations, such as forEach(), mark the stream as consumed, after which point it can no longer be used further.
Intermediate operations such as filter() return a new stream on which further processing can be done.
A stream pipeline consists of a stream source, followed by zero or more intermediate operations, and a terminal operation. -
Comparison based stream operations:
containing: sorted, min, max, distinct, allMatch, anyMatch, noneMatch -
Stream specialization:
IntStream, DoubleStream, LongStream etc.
网友评论