Java8 的 List 与 Consumer 或 Filter 的条件,哪种方式更好
Conditions for a List with Java8 with Consumer or Filter, which way is better
我试过了
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);
但是不知道哪个更好,我觉得是forEach和Consumer,但是Consumer做了3次验证,所以不是单一职责
消费者只进行一次迭代,因此效率更高,而且它确实有一个单一的职责:根据数字的符号将数字分成三个列表。
对于这种情况,我可能会使用一个简单的 for
循环。
如果你真的想要over-engineer的东西,你可以定义一个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}
这会产生以下输出:
{ZERO=[0], POSITIVE=[1, 1], NEGATIVE=[-1, -1]}
注意: 如果您希望地图中的未来查找达到最佳性能,您可以改用 EnumMap
。看看 看看如何。
我通常更喜欢您基于 Consumer
的解决方案,因为它至少将整个操作封装在一个 call/stream 中。但我认为您还没有充分利用流的功能方法。
您可以使用简单的 stream/collect 来实现此排序:
numbers .stream()
.collect(Collectors.groupingBy(Math::signum));
将生成如下地图:
{1.0=[1], 0.0=[0, 0], -1.0=[-1, -2, -1]}
这种方法避免了副作用(即不修改流范围之外的列表),因此可以更容易地提取并且很容易 运行 并行。
我试过了
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);
但是不知道哪个更好,我觉得是forEach和Consumer,但是Consumer做了3次验证,所以不是单一职责
消费者只进行一次迭代,因此效率更高,而且它确实有一个单一的职责:根据数字的符号将数字分成三个列表。
对于这种情况,我可能会使用一个简单的 for
循环。
如果你真的想要over-engineer的东西,你可以定义一个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}
这会产生以下输出:
{ZERO=[0], POSITIVE=[1, 1], NEGATIVE=[-1, -1]}
注意: 如果您希望地图中的未来查找达到最佳性能,您可以改用 EnumMap
。看看
我通常更喜欢您基于 Consumer
的解决方案,因为它至少将整个操作封装在一个 call/stream 中。但我认为您还没有充分利用流的功能方法。
您可以使用简单的 stream/collect 来实现此排序:
numbers .stream()
.collect(Collectors.groupingBy(Math::signum));
将生成如下地图:
{1.0=[1], 0.0=[0, 0], -1.0=[-1, -2, -1]}
这种方法避免了副作用(即不修改流范围之外的列表),因此可以更容易地提取并且很容易 运行 并行。