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

How do I filter through a list of objects that contains lists?

假设我有一个 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
            },
            ...
        ]
    }
]

然后将其解析为对象列表并调用此列表提供程序。 我该如何处理 filtering/streaming 这个列表,找到正确的供应商然后突破?

我试过类似下面的方法:

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

由于您没有提供任何 classes 我已经尝试了以下结构:

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;

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

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 class,您可以像这样简单地嵌套流:

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)

这将 return 第一个 Field 匹配所提供的 Role.providedFor

来自flatMap JavaDocs:

Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.

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

最后,findfirst 方法 return 是第一场比赛。这意味着可能没有匹配项,因此 Optional 被 return 编辑。 Optional class 具有检索底层对象并检查其是否存在的方法(get()isPresent())。查看 Optional JavaDocs 了解更多信息。