class A {
double value;
String key;
}
class B {
List<A> aList;
}
Given List<B> bList
, I want to calculate the average of the value
s for a specific key k
. Assume each B
can hold only 0 or 1 times an instance of A
with key.equals(k)
.
I figured I could first filter aList
, and later extract the value using mapToDouble
:
double average = blist.stream().filter(
b -> b.aList.stream().anyMatch(
a -> a.key.equals(k)
)
).mapToDouble(
b -> b.aList.stream().filter(
a -> a.key.equals(k)
).findFirst().get().value
).average().orElse(0);
But there is clearly a redundancy here, since I am filtering the same list by the same predicate twice ( a -> a.key.equals(k)
).
Is there a way to mapToDouble
while omitting elements with missing matching key
s at the same time?
Edit:
Here is a more concrete example, hopefully it will make it easier to understand:
String courseName;
...
double average = students.stream().filter(
student -> student.getGrades().stream().anyMatch(
grade -> grade.getCourseName().equals(courseName)
)
).mapToDouble(
student -> student.getGrades().stream().filter(
grade -> grade.getCourseName().equals(courseName)
).findFirst().get().getValue()
).average().orElse(0);
System.out.println(courseName + " average: " + average);
Try this:
double average = bList.stream()
.flatMap(b -> b.aList.stream())
.filter(a -> a.key.equals(k))
.mapToDouble(a -> a.value)
.average()
.orElse(Double.NaN);
If your objects have private field and getters, which they really should, it'd be like this:
double average = bList.stream()
.map(B::getaList)
.flatMap(List::stream)
.filter(a -> a.getKey().equals(k))
.mapToDouble(A::getValue)
.average()
.orElse(Double.NaN);
Try this.
double average = blist.stream()
.map(b -> b.aList.stream()
.filter(a -> a.key.equals(k))
.findFirst())
.filter(a -> a.isPresent())
.mapToDouble(a -> a.get().value)
.average().orElse(0);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.