根据可选列表过滤列表

Filter List based of optional List

我有一个可选的整数列表, Optional<List<Integer>> id.

我有很多不同的人的名单。 List<People> people.

我有一个采用可选过滤器的过滤器方法。该代码调用存储库以获取人员列表,如果填充了可选的 id 列表,则会根据 id 过滤列表中的人员。 People.getId()。

我想使用 steams API 以避免编辑原始列表。我试过这样的东西

 return people.stream()
            .filter(p -> !request.getId().orElseGet(ArrayList::new).contains(p.getId()))
            .collect(Collectors.toList());

规格是。

当没有 id 匹配时以上失败,它 return 是一个完整列表。

Optional<List<Integer>> ids = Optional.of(Arrays.asList(1, 2, 3));
List<People> people = datasource...

List<People> filter (Optional < List < Integer >>> ids) {
    List<People> confusion = people.steam(). ?
    return confusion;
}

非常感谢任何帮助!

就这些了。

List<People> filter (Optional < List < Integer >>> idsOpt) {
    return 
        idsOpt.map(
            ids ->
                people.stream()
                    .filter(p -> ids.contains(p.getId())
                        .collect(Collectors.toList())
        ).orElse(people);
}

if no id's, return all

首先,你只需要一个||条件。如果 Optional 为空,则 Optional.isPresent() 将是 false,因此在 || 之前添加 !ids.isPresent() 将 return 您的所有项目从 filter 因为 || 是一个短路操作,因为 || 左边的条件是 true 整个条件将是 true

if id's provided - filter

其次,! 需要从您的支票中删除,您需要在 || 右侧进行此支票:ids.get().contains(p.getId()) 以使用来自Optional.

if id's provided and no matches, return empty list

第三,如果 ids 存在,则第二个检查将被评估为第一个检查 !ids.isPresent() 变为 false。如果 idOptional 中的列表匹配,则将检查 People 对象 如果没有匹配,则空列表是 returned.

所以下面三个都可以应用:

List<People> list = people.stream()
                        .filter(p -> !ids.isPresent() || ( ids.get().isEmpty() || ids.get().contains(p.getId())))
                        .collect(Collectors.toList());

此外,如果您使用 Optional<Set<Integer>> 而不是 Optional<List<Integer>> 会更好,那么 contains() 将是常数时间操作。

First, we eliminate case when the user gave us no input.

if (ids == null || !ids.isPresent() || ids.get().isEmpty())
    return getPeopleFromSomewhere();

Second, we handle a scenario where a user actually gave us something

people.stream()
        .filter(p -> ids.get().stream().anyMatch(id -> id.equals(p.getId())))
        .collect(Collectors.toList());

Eventually, if the user gave us the ids, that do not match, we will return the filtered empty list.

最终版本看起来像这样。

public List doSomething() {
    Optional<List<Integer>> ids = Optional.of(Arrays.asList(1,2,3));
    List<People> people = getPeopleFromSomewhere();

    if (ids == null || !ids.isPresent() || ids.get().isEmpty())
        return people;

    return people.stream()
            .filter(p -> ids.get().stream().anyMatch(id -> id.equals(p.getId())))
            .collect(Collectors.toList());

}

有效解决该问题的方法之一是

List<People> filteringOperation(Optional<List<Integer>> id, List<People> people) {
    Set<Integer> uniqueIds = id.isPresent() ? new HashSet<>(id.get()) : Collections.emptySet();
    return uniqueIds.isEmpty() ? people : people.stream()
            .filter(p -> uniqueIds.contains(p.getId()))
            .collect(Collectors.toList());
}

以上遵循如下规范:

  • 如果没有 id,return 全部

如果 id 列表为空,则 uniqueIds 将为空,所有 people 的现有列表将为 returned。

  • 如果提供了 id - 过滤器

如果 id 列表有值,这些值将被收集到 Set 中,并且 ID 包含在该集合中的人将在结果列表中被过滤。

  • 如果提供了 id 但没有匹配,return 空列表

流实现还意味着如果提供的 ID 与人员列表中的任何人都不匹配,则会 return 编辑一个空列表。