简体   繁体   English

带有使用者或过滤器的Java8的List的条件,哪种方式更好

[英]Conditions for a List with Java8 with Consumer or Filter, which way is better

I have tried this 我试过这个

    List<Integer> numbers = Arrays.asList(1, 1, 0, -1, -1);
    List<Integer> positiveNum2 = new ArrayList<>();
    List<Integer> negativeNum2 = new ArrayList<>();
    List<Integer> zeroNumbers2 = new ArrayList<>();
    List<Integer> positiveNumbers = numbers.stream().filter(number -> number > 0).collect(Collectors.toList());
    List<Integer> negativeNumbers = numbers.stream().filter(number -> number < 0).collect(Collectors.toList());
    List<Integer> zeroNumbers = numbers.stream().filter(number -> number.equals(0)).collect(Collectors.toList());
    positiveNumbers.forEach(System.out::println);
    negativeNumbers.forEach(System.out::println);
    zeroNumbers.forEach(System.out::println);
    System.out.println("*********with Consumer******************");
    Consumer<Integer> determineNumber = number -> {
        if (number > 0) {
            positiveNum2.add(number);
        } else if (number < 0) {
            negativeNum2.add(number);
        } else {
            zeroNumbers2.add(number);
        }

    };
    numbers.forEach(determineNumber);
    positiveNum2.forEach(System.out::println);
    negativeNum2.forEach(System.out::println);
    zeroNumbers2.forEach(System.out::println);

but I dont know which one is better, I think the forEach with the Consumer, but the Consumer does three validations, therefore, does not have single responsability 但我不知道哪一个更好,我认为forEach与消费者,但消费者进行三次验证,因此,没有单一的责任

I would generally prefer your Consumer based solution as it at least encapsulates the whole operation in one call/stream. 我通常更喜欢基于Consumer的解决方案,因为它至少将整个操作封装在一个调用/流中。 But I think you don't yet take full advantage of the functional approach of streams. 但我认为你还没有充分利用流的功能方法。

You could use a simple stream/collect to achieve this sorting: 您可以使用简单的流/收集来实现此排序:

numbers .stream()
        .collect(Collectors.groupingBy(Math::signum));

will result in a map like this: 将导致这样的地图:

{1.0=[1], 0.0=[0, 0], -1.0=[-1, -2, -1]}

This approach avoids side effects (ie does not modify lists outside of the stream's scope) and can hence be extracted more easily and is easily run in parallel. 这种方法避免了副作用(即不修改流范围之外的列表),因此可以更容易地提取并且易于并行运行。

The consumer only takes one iteration, so it's more efficient, and it does have a single responsibility: dividing the numbers over three lists based on their sign. 消费者只需要一个迭代,所以它的效率更高,而且它有一个责任:将数字还将基于他们的标志三个列表。

For this case, I'd probably use a simple for loop though. 对于这种情况,我可能会使用一个简单的for循环。

If you really want to over-engineer things, you can define an enum to represent the sign, and use a grouping collector to group into a map: 如果你真的想要过度设计,你可以定义一个enum来表示符号,并使用分组收集器分组到一个地图中:

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static java.util.stream.Collectors.groupingBy;

public class Test {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 1, 0, -1, -1);

        Map<Sign, List<Integer>> map = numbers
                .stream()
                .collect(groupingBy(i -> i > 0
                                    ? Sign.POSITIVE
                                    : i < 0 
                                        ? Sign.NEGATIVE
                                        : Sign.ZERO));

        System.out.println(map);
    }
}

enum Sign {POSITIVE, NEGATIVE, ZERO}

This yields the following output: 这会产生以下输出:

{ZERO=[0], POSITIVE=[1, 1], NEGATIVE=[-1, -1]}

Note: If you want peak performance for future lookups in your map, you can use an EnumMap instead. 注意:如果您希望将来在地图中进行查找具有最佳性能,则可以使用EnumMap Take a look at this answer to see how. 看看这个答案 ,看看如何。

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

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