Java 8中的Stream过滤列表中的列表值

14

我有一个对象,它看起来像下面这样

class MyObject {

    String type;
    List<String> subTypes;

}

在给定MyObject列表的情况下,是否可以使用Java 8流来先过滤类型,然后再过滤子类型?

目前我已经有了以下代码:

myObjects.stream()
    .filter(t -> t.getType().equals(someotherType)
    .collect(Collections.toList());

但是在此基础上,我还想对每个子类型中的特定子类型进行另一个过滤器。我无法弄清楚如何实现。

例如:

myObject { type: A, subTypes [ { X, Y, Z } ] }
myObject { type: B, subTypes [ { W, X, Y } ] }
myObject { type: B, subTypes [ { W, X, Z } ] }
myObject { type: C, subTypes [ { W, X, Z } ] }

我会传入匹配类型为B和子类型为Z,因此我期望得到一个结果-> 我的对象类型为B,子类型包括W、X、Z。
以下代码目前返回列表中的2个项目。
myObjects.stream()
    .filter(t -> t.getType().equals("B")
    .collect(Collectors.toList());

但我希望在每个子类型上添加一个额外的过滤器,只匹配包含“Z”的内容。


你能举一个匹配和不匹配的例子吗?subTypes中的所有元素都必须匹配吗? - user1907906
你想过滤 subTypes 吗? - kraskevich
“在每个子类型上添加另一个过滤器来过滤特定子类型的内容”这句话具体是什么意思?请举个例子。 - user1907906
3个回答

20

您可以:

myObjects.stream()
         .filter(t -> t.getType().equals(someotherType) && 
                      t.getSubTypes().stream().anyMatch(<predicate>))
         .collect(Collectors.toList());

这将获取所有符合以下条件的MyObject对象:
  • 满足type成员的标准。
  • 包含在嵌套的List<String>中满足某些其他标准的对象,用<predicate>表示。

anymatch做到了:3 - Supun Wijerathne

13

我看到了来自@kocko的被接受的答案,这是一个很好而且完全正确的答案。然而,还有一种稍微不同的方法,就是简单地链接过滤器。

final List<MyObject> withBZ = myObjects.stream()
        .filter(myObj -> myObj.getType().equals("B"))
        .filter(myObj -> myObj.getSubTypes().stream().anyMatch("Z"::equals))
        .collect(Collectors.toList());

这基本上做了相同的事情,但是&&操作符被另一个过滤器代替。对于Java 8 Stream API,链接非常有效,并且我认为它更易于阅读和跟踪代码。


我同意最后一句话。谢谢。 - Konstantin Yovkov
2
有没有使用.stream().anyMatch("Z"::equals)而不是只使用.contains("Z")的原因?不确定我是否遗漏了什么或它们实际上是相同的。 - Alex Pritchard

0

我在这个网站上找到了很多例子:https://zetcode.com/java/streamfilter/

引用Java Stream多重过滤操作的示例:

可以在流上应用多个过滤操作。

package com.zetcode;

import java.util.Arrays;
import java.util.function.IntConsumer;

public class JavaStreamMultipleFilters {

public static void main(String[] args) {

    int[] inums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
    
    IntConsumer icons = i -> System.out.print(i + " ");
    
    Arrays.stream(inums).filter(e -> e < 6 || e > 10)
            .filter(e -> e % 2 == 0).forEach(icons);
}

}

在这个例子中,我们对一个整数流应用多个过滤操作。
int[] inums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

我们有一个整数值的数组。

IntConsumer icons = i -> System.out.print(i + " ");

IntConsumer是一个接受单个整数值参数并返回无结果的操作。

Arrays.stream(inums).filter(e -> e < 6 || e > 10)
        .filter(e -> e % 2 == 0).forEach(icons);

使用Arrays.stream方法从数组创建一个流。执行多个过滤操作。

2 4 12 14

这些整数满足所有的过滤条件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接