使用Java 8筛选结果集的多个条件



我正在寻找一些转换代码的帮助,我必须使用非常漂亮的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而编的一个超级做作的例子。假设所有学生都是从具有studentIdclassRoomId的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());

最新更新