基于不同字段的java流过滤器

时间:2017-10-10 00:40:10

标签: java java-8 java-stream

我有一个对象Person流。我想找到身高> 6的人,如果没有符合该标准的人,那么我想找到体重> 100的人。我是通过以下方式实现它,但想知道我能否以更好的方式完成它。

Optional<Person> personWithHeightGreaterThan6 = persons.stream()
        .filter(person -> person.getHeight()>6)
        .findFirst();
if (personWithHeightGreaterThan6.isPresent()) {
        result = personWithHeightGreaterThan6.get();
} else {
Optional<Person> personWithWeightGreaterThan100 = persons.stream()
        .filter(person -> person.getWeight()>100)
        .findFirst();
    if (personWithWeightGreaterThan100.isPresent()) {
            result = personWithWeightGreaterThan100.get();
        }
    }

2 个答案:

答案 0 :(得分:3)

http://flazzin.com//api.php?latest可以简化为

@SafeVarargs
static <T> T findFirst(List<T> elements, Predicate<? super T>... filters) {
    return Arrays.stream(filters)
            .flatMap(f -> elements.stream().filter(f))
            .findFirst()
            .orElse(null);
}

不幸的是,对于当前的Stream实现,使用flatMap与其他解决方案相比具有较小的性能劣势,如“shmosel’s answer”中所述,但对于大多数实际用例,它可能就足够了。

Java 9提供了一个完全懒惰的中间解决方案,几乎和上面的一样简单:

@SafeVarargs
static <T> T findFirst(List<T> elements, Predicate<? super T>... filters) {
    return Arrays.stream(filters)
            .flatMap(f -> elements.stream().filter(f).findFirst().stream())
            .findFirst()
            .orElse(null);
}

答案 1 :(得分:2)

这是一种尝试通过匹配按优先级排序的过滤器数组来查找元素的方法。如果它没有找到与任何过滤器的匹配,它将返回null。

@SafeVarargs
static <T> T findFirst(List<T> elements, Predicate<? super T>... filters) {
    return Arrays.stream(filters)
            .map(f -> elements.stream().filter(f).findFirst())
            .filter(Optional::isPresent)
            .map(Optional::get)
            .findFirst()
            .orElse(null);
}

您可以这样称呼它:

Person result = findFirst(persons,
        person -> person.getHeight() > 6,
        person -> person.getWeight() > 100);

可能有点矫枉过正,但不清楚你正在寻找什么样的改善。