如何筛选包含列表的对象列表?

时间:2015-02-04 20:25:07

标签: java filter java-8 java-stream

想象一下,我有一个类似以下的json:

[
    {
        field: string,
        roles: [
            {
                id: int,
                providedFor: int
            },
            {
                id: int,
                providedFor: int
            },
            ...
        ]
    },
    {
        field: string,
        roles: [
            {
                id: int,
                providedFor: int
            },
            {
                id: int,
                providedFor: int
            },
            ...
        ]
    },
    {
        field: string,
        roles: [
            {
                id: int,
                providedFor: int
            },
            {
                id: int,
                providedFor: int
            },
            ...
        ]
    }
]

这将解析为对象列表并调用此列表提供程序。 我怎样才能过滤/流式传输此列表,找到正确的提供商然后突破?

我尝试过以下内容:

providers.parallelStream().filter(p -> p.getRoles().parallelStream().filter(r -> r.getProvidedFor.equal("something")).findFirst());

1 个答案:

答案 0 :(得分:3)

由于您没有提供任何课程,我已尝试使用以下结构:

class Field {
    String field;
    List<Role> roles;

    Field(String field, List<Role> roles) {
        this.field = field;
        this.roles = roles;
    }
}

class Role {
    int id;
    int providedFor;

    Role(int id, int providedFor) {
        this.id = id;
        this.providedFor = providedFor;
    }
}

Field是外部对象,Role是内部对象。因此,如果您构建ListField个像这样的对象:

final List<Field> fields = Arrays.asList(
        new Field("f11", Arrays.asList(new Role(11, 11), new Role(11, 12))),
        new Field("f22", Arrays.asList(new Role(22, 22), new Role(22, 23))),
        new Field("f33", Arrays.asList(new Role(33, 33), new Role(33, 34))));

而且,您正在搜索something

int something = 22;

您可以使用Role方法过滤掉flatMap,如下所示:

final Optional<Role> first = fields.stream()
        .flatMap(f -> f.roles.stream())          // Chain all "substreams" to one stream
        .filter(r -> r.providedFor == something) // Check for the correct object
        .findFirst();                            // Find the first occurrence

请注意,如果providedFor不是原始的,但应使用某种Object equals方法。

如果你正在寻找Field类,你可以简单地嵌套这样的流:

final Optional<Field> firstField = fields.stream()
        .filter(f -> f.roles.stream()                       // Nested stream
                .anyMatch(r -> r.providedFor == something)) // Return true if present
        .findFirst();                                       // Find the first Field object (findAny can be used here as well if "any" hit is ok)

这将返回与提供的Field匹配的第一个Role.providedFor

来自flatMap JavaDocs

  

返回一个流,该流包含将此流的每个元素替换为通过将提供的映射函数应用于每个元素而生成的映射流的内容的结果。

基本上你是嵌套流链接到一个流。

最后,findfirst方法返回第一个匹配项。这意味着可能没有匹配,因此返回OptionalOptional类具有检索基础对象并检查其是否存在的方法(get()isPresent())。查看Optional JavaDocs了解详情。