[英]Java stream API - avoid using same predicate twice to calculate average
class A {
double value;
String key;
}
class B {
List<A> aList;
}
給定List<B> bList
,我想計算特定密鑰k
的value
s的平均值。 假設每個B
只能用key.equals(k)
保持A
的實例的0或1倍。
我想我可以先過濾aList
,然后使用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);
但是這里顯然有一個冗余,因為我用相同的謂詞過濾相同的列表兩次( a -> a.key.equals(k)
)。
有沒有辦法mapToDouble
同時省略缺少匹配key
s的元素?
編輯:
這是一個更具體的例子,希望它更容易理解:
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);
嘗試這個:
double average = bList.stream()
.flatMap(b -> b.aList.stream())
.filter(a -> a.key.equals(k))
.mapToDouble(a -> a.value)
.average()
.orElse(Double.NaN);
如果你的對象有私有字段和getter,他們真的應該這樣,它就像這樣:
double average = bList.stream()
.map(B::getaList)
.flatMap(List::stream)
.filter(a -> a.getKey().equals(k))
.mapToDouble(A::getValue)
.average()
.orElse(Double.NaN);
嘗試這個。
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.