-
Enhancement
-
Resolution: Unresolved
-
P4
-
8u45, 9
A DESCRIPTION OF THE PROBLEM :
When using the Stream API, I'm always struggling with the question: what is the best way to construct a Stream pipeline?
There are so many possibilities:
- use a single map() operation with a chain of method invocations
vs use a chain of map() operations
- use a flatMap() operation
vs use a separate filter() and map() operation
- use simple lambda expressions of the form e -> e.getId()
vs use method references
etc.
And also: are the choices affected by the parallel-ness of the Stream? For example, maybe it's better to use a chain of map() operations for parallel streams, while it's better to use a single map() operation for sequential streams?
As an example, the following 3 (and many more variations are possible) Stream pipelines do the exact same thing. The API documentation should provide guidance on when to choose which variant. It should also document the "why", by explaining how the Stream API works.
employees.stream()
.flatMap(e -> e.isFTE() ? Stream.of(BigDecimal.valueOf(e.getId().getChecksum())) : Stream.empty())
.anyMatch(checksum -> checksum.equals(BigDecimal.ZERO));
employees.stream()
.filter(e -> e.isFTE())
.map(e -> BigDecimal.valueOf(e.getId().getChecksum()))
.anyMatch(checksum -> checksum.equals(BigDecimal.ZERO));
employees.stream()
.filter(Employee::isFTE)
.map(Employee::getId)
.mapToLong(EmployeeId::getChecksum)
.mapToObj(BigDecimal::valueOf)
.anyMatch(checksum -> checksum.equals(BigDecimal.ZERO));
For reference, the classes Employee & EmployeeId:
public class Employee {
private final EmployeeId id = new EmployeeId();
public EmployeeId getId() {
return id;
}
public boolean isFTE() {
return true;
}
}
public class EmployeeId {
private final long checksum = 42;
public long getChecksum() {
return checksum;
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An extra section in the java.util.stream package which documents best practices for creating pipelines & all the trade-offs that are involved.
ACTUAL -
No such documentation is provided with the JDK.
URL OF FAULTY DOCUMENTATION :
http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
When using the Stream API, I'm always struggling with the question: what is the best way to construct a Stream pipeline?
There are so many possibilities:
- use a single map() operation with a chain of method invocations
vs use a chain of map() operations
- use a flatMap() operation
vs use a separate filter() and map() operation
- use simple lambda expressions of the form e -> e.getId()
vs use method references
etc.
And also: are the choices affected by the parallel-ness of the Stream? For example, maybe it's better to use a chain of map() operations for parallel streams, while it's better to use a single map() operation for sequential streams?
As an example, the following 3 (and many more variations are possible) Stream pipelines do the exact same thing. The API documentation should provide guidance on when to choose which variant. It should also document the "why", by explaining how the Stream API works.
employees.stream()
.flatMap(e -> e.isFTE() ? Stream.of(BigDecimal.valueOf(e.getId().getChecksum())) : Stream.empty())
.anyMatch(checksum -> checksum.equals(BigDecimal.ZERO));
employees.stream()
.filter(e -> e.isFTE())
.map(e -> BigDecimal.valueOf(e.getId().getChecksum()))
.anyMatch(checksum -> checksum.equals(BigDecimal.ZERO));
employees.stream()
.filter(Employee::isFTE)
.map(Employee::getId)
.mapToLong(EmployeeId::getChecksum)
.mapToObj(BigDecimal::valueOf)
.anyMatch(checksum -> checksum.equals(BigDecimal.ZERO));
For reference, the classes Employee & EmployeeId:
public class Employee {
private final EmployeeId id = new EmployeeId();
public EmployeeId getId() {
return id;
}
public boolean isFTE() {
return true;
}
}
public class EmployeeId {
private final long checksum = 42;
public long getChecksum() {
return checksum;
}
}
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
An extra section in the java.util.stream package which documents best practices for creating pipelines & all the trade-offs that are involved.
ACTUAL -
No such documentation is provided with the JDK.
URL OF FAULTY DOCUMENTATION :
http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html