简体   繁体   English

Java 流通过多个过滤器执行不同的操作

[英]Java streams perform different operations by multiple filters

I want to return different error messages minimum and maximum constraints on the values in a given list.我想针对给定列表中的值返回不同的错误消息最小和最大限制。 I was hoping to use Java streams but i am having to filter the same list twice.我希望使用 Java 流,但我不得不两次过滤相同的列表。 Whereas using a for loop i would only have to go over the list once.而使用 for 循环我只需要 go 遍历列表一次。 Is there a better way to achieve this via streams?有没有更好的方法通过流来实现这一点?

My code looks something like this:我的代码看起来像这样:

list.stream().filter(i -> i < 0).findAny().ifPresent(i -> System.out.println("below min"));

list.stream().filter(i -> i > 100).findAny().ifPresent(i -> System.out.println("above max"));

Using a for loop i can place two if conditions while traversing over the list once,使用 for 循环我可以放置两个 if 条件,同时遍历列表一次,

In actual implementation there are other constraints as well and I'm adding an error to a list, if it not already exists, depending on each violation.在实际实施中,还有其他约束,如果错误不存在,我会根据每次违规情况向列表中添加一个错误。

Will i have to filter the list each time for each violation?每次违规我都必须过滤列表吗? Help would be appreciated!帮助将不胜感激!

If you are using Java 12+ you can utilize teeing collector to achieve what you want using Java Streams API:如果您使用的是Java 12+ ,您可以利用发球收集器使用 Java Streams API 来实现您想要的:

list.stream()
    .collect(Collectors.teeing(
        Collectors.minBy(Comparator.comparingInt(Integer.class::cast)),
        Collectors.maxBy(Comparator.comparingInt(Integer.class::cast)),
            (min, max) -> {
              min.ifPresent(i -> System.out.println("below min"));
              max.ifPresent(i -> System.out.println("above max"));
              return 0;
            }
    ));

You can collect those elements as well:您也可以收集这些元素:

list.stream()
    .collect(Collectors.teeing(
        Collectors.filtering(i -> i < 0, Collectors.toList()),
        Collectors.filtering(i -> i > 100, Collectors.toList()),
            (l1, l2) -> {
              System.out.printf("%s %s%n", l1, l2);
              return 0;
            }
    ));

Though, whether such approach with streams should be used in place of a for loop needs careful consideration.但是,是否应该使用这种流方法代替for循环需要仔细考虑。 For this specific question, the code using the for loop will probably be more readable.对于这个特定问题,使用for循环的代码可能更具可读性。

You can simply stream and use a forEach loop to filter out elements in a single loop:您可以简单地使用 stream 并使用 forEach 循环在单个循环中过滤掉元素:

        List<Integer> smaller = new ArrayList<>();
        List<Integer> larger = new ArrayList<>();
        List<Integer> intList = Arrays.asList(200, 345, -132, -2, -34, null);

        intList.stream().filter(Objects::nonNull).forEach(element -> {
            if (element < 0) {
                smaller.add(element);
            } else if (element > 100) {
                larger.add(element);
            }
        });
        System.out.println("Smaller:-" + smaller);
        System.out.println("Larger:-" + larger);

The real focus should be on code readability even if it takes some more code line to write logic.真正的重点应该放在代码的可读性上,即使需要更多的代码行来编写逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM