我正在寻找一些转换代码的帮助,我必须使用非常漂亮的Java 8 Stream库。本质上,我有一堆学生对象,我想得到一个过滤对象的列表,如下所示:
List<Integer> classRoomList;
Set<ScienceStudent> filteredStudents = new HashSet<>();
//Return only 5 students in the end
int limit = 5;
for (MathStudent s : mathStudents)
{
// Get the scienceStudent with the same id as the math student
ScienceStudent ss = scienceStudents.get(s.getId());
if (classRoomList.contains(ss.getClassroomId()))
{
if (!exclusionStudents.contains(ss))
{
if (limit > 0)
{
filteredStudents.add(ss);
limit--;
}
}
}
}
当然,上面是我为了学习更多Java 8而编的一个超级做作的例子。假设所有学生都是从具有studentId
和classRoomId
的Student对象扩展而来的。我需要的另一个要求是,结果是不可变集。
一个相当字面的翻译(以及所需的类)
interface ScienceStudent {
String getClassroomId();
}
interface MathStudent {
String getId();
}
Set<ScienceStudent> filter(
Collection<MathStudent> mathStudents,
Map<String, ScienceStudent> scienceStudents,
Set<ScienceStudent> exclusionStudents,
List<String> classRoomList) {
return mathStudents.stream()
.map(s -> scienceStudents.get(s.getId()))
.filter(ss -> classRoomList.contains(ss.getClassroomId()))
.filter(ss -> !exclusionStudents.contains(ss))
.limit(5)
.collect(Collectors.toSet());
}
要过滤的多个条件实际上只是转换为多个.filter
调用或像ss -> classRoomList.contains(ss.getClassroomId()) && !exclusion...
这样的组合大过滤器
关于不可变集合:最好手动将其包装在结果中,因为collect
期望一个可变集合,该集合可以从流中填充并在完成后返回。我认为没有一种简单的方法可以直接用流来做到这一点。
null
偏执版
return mathStudents.stream().filter(Objects::nonNull) // math students could be null
.map(MathStudent::getId).filter(Objects::nonNull) // their id could be null
.map(scienceStudents::get).filter(Objects::nonNull) // and the mapped science student
.filter(ss -> classRoomList.contains(ss.getClassroomId()))
.filter(ss -> !exclusionStudents.contains(ss))
.limit(5)
.collect(Collectors.toSet());