Converting code to use Stream
pipelines can be slightly difficult due to multiple reasons, such as unfamiliarity with the API, or an inability to visualise.
This is a common question for PEs (specifically PE2).
An approach could be:
- Consider how the question would be approached without considering functional programming.
- Think of the relevant API calls.
Example
Consider a list of students, where each student has an attribute
marks
which is adouble[]
containing all their marks for all their assessments, as well as aname
which can be obtained fromgetName()
. TheStudent
class also contains a methodgetMarks(double[] weights)
, which obtains the total mark based on the weights passed in.Given another
double[],
weights
which contains the weights of the assessments, get the list of students that score above a given markthreshold
.
Doing this normally, we would
- calculate all the marks for each student AND
- remove all students not above threshold/add all students above threshold to a new list
- get the names
List<String> getStudentsAboveThreshold(List<Student> students,
double[] weights, double threshold) {
List<String> result = new ArrayList<String>();
for (Student s : students) {
if (s.getMarks(weights) > threshold) {
result.add(student.getName());
}
}
return result;
}
Now, if we think of it from the Stream
pipeline perspective,
- we can
filter
all the students above threshold - we can
map
theStudent
objects into their names.
List<String> getStudentsAboveThreshold(List<Student> students,
double[] weights, double threshold) {
return Stream.of(students)
.filter(s -> s.getMarks(weights) > threshold) // step 1
.map(s -> s.getName()) // step 2
.toList(); // since they want a List<String>
}