【问题标题】:Filter List based of optional List根据可选列表过滤列表
【发布时间】:2019-09-03 15:34:08
【问题描述】:

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

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

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

我想使用 Steams API 来避免编辑原始列表。我尝试过这样的事情

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

规格是。

  • 如果没有id,则全部返回
  • 如果提供了 ID - 过滤器
  • 如果提供的 id 没有匹配,则返回空列表

上面的失败,当没有id的匹配,它返回一个完整的列表。

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;
}

非常感谢任何和所有帮助!

【问题讨论】:

  • 这里不需要 Java8 和 Optionals。只需使用 for 循环并执行此操作。 Java8 不是解决所有问题的灵丹妙药。
  • Optional 一般不推荐用于参数。如果调用者仅在他们真正想要完成过滤时调用filter,它将为您提供更清晰的界面。调用者可以做类似filteredList = ids.map(this::filter).orElse(people);.

标签: java java-stream optional


【解决方案1】:

如果没有id,则全部返回

首先,您只需要一个|| 条件。如果Optional 为空,则Optional.isPresent() 将为false,因此在|| 之前添加!ids.isPresent() 将返回filter 中的所有项目,因为|| 是一个short- ||左边的条件是true,整个条件是true

如果提供了 id - 过滤器

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

如果提供了 id 并且没有匹配,则返回空列表

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

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

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

另外,如果您使用Optional&lt;Set&lt;Integer&gt;&gt; 而不是Optional&lt;List&lt;Integer&gt;&gt; 会更好,那么contains() 将是常数时间操作。

【讨论】:

    【解决方案2】:

    首先,我们消除用户没有输入的情况。

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

    其次,我们处理用户实际给我们东西的场景

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

    最终,如果用户给我们的 id 不匹配,我们将返回过滤后的空列表。

    最终版本将类似于这些内容。

    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());
    
    }
    

    【讨论】:

      【解决方案3】:

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

      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,则全部返回

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

      • 如果提供了 ID - 过滤器

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

      • 如果提供的 id 没有匹配,则返回空列表

      流实现还意味着,如果提供的 id 与人员列表中的任何人都不匹配,则将返回一个空列表。

      【讨论】:

        【解决方案4】:

        就是这样。

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

        【讨论】:

          猜你喜欢
          • 2021-06-17
          • 2023-03-22
          • 1970-01-01
          • 2023-03-11
          • 2021-06-23
          • 2021-09-16
          • 2020-10-09
          • 2013-09-11
          • 2012-08-07
          相关资源
          最近更新 更多