Java 8 Stream Api过滤器特定范围

时间:2019-03-21 07:34:52

标签: java java-stream

我有一个这样的列表:

int[] counting = new int[]{1,0,-1,-2,-1,-2,-1,0,1,2,1,0,-1,0,1,2};

我要过滤0到0之间的负值。

对于上面的列表,结果应返回2,因为0到0之间存在一个负数,并且对于第三个范围也有效。

List<Integer> result = Arrays.stream(counting).filter(x ->  ).collect(Collectors.toList());

如何收集范围值?之后,如何检查是否有负数?

换句话说,我想计算之间有一个负值的(0,0)对。因此,由于-1,-2,-1,-2,-1的值为负,而-1的值为1,因此此类对的数量为2。

3 个答案:

答案 0 :(得分:3)

请勿为此使用流管道。流非常适合元素的独立处理和过滤。它们不适合依赖于流中是否存在其他元素的处理(此处早晚为0)。

使用循环。在进入循环之前,请检查列表中的第一个元素是否为0(如果需要),如果不是,则抛出异常(因此问题中的示例列表将无法通过此测试)。声明我们在循环期间需要的一些变量:

   int negativeCount = 0;
   boolean hasSeenNegativeSinceLastZero = false;

在循环中,每次看到负数时,请将hasSeenNegativeSinceLastZero设置为true。每次看到0时,如果hasSeenNegativeSinceLastZero为true,则将1加到计数并将hasSeenNegativeSinceLastZero设置为false。

快乐的编码。

答案 1 :(得分:1)

这是基于流的解决方案。我怀疑它比简单的for循环更具可读性。

int[] zeroIndices = IntStream.range(0, counting.length)
                .filter(i -> 0 == counting[i])
                .toArray();

long count = IntStream.range(0, zeroIndices.length)
        .mapToObj(i -> new int[] { i, zeroIndices[i] })
        .skip(1)
        .filter(arr -> Arrays.stream(Arrays.copyOfRange(counting, 
                                                        zeroIndices[arr[0] - 1], 
                                                        arr[1]))
                             .anyMatch(i -> i < 0))
        .count();

答案 2 :(得分:0)

我个人认为流解决方案不可读,您应该使用简单的循环,但是可以混合使用。我想这里应该是这样

int[] counting = new int[] {1, 0, -1, -2, -1, -2, -1, 0, 1, 2, 1, 0, -1, 0, 1, 2};

List<Integer> indices = new ArrayList<>();
for (var i = 0; i < counting.length; i++) {
  if (counting[i] == 0) {
    indices.add(i);
  }
}

if (indices.size() % 2 == 0) {
  System.out.println("You got " + indices.size() / 2 + " pairs");
} else {
  System.err.println(
      "You don't have complete pairs, you have only " + indices.size() / 2 + " pairs");
  System.exit(-1);
}

for (var i = 0; i < indices.size(); i = i + 2) {
  System.out.println("-----Pair----");
  stream(copyOfRange(counting, indices.get(i), indices.get(i + 1)))
      .filter(v -> v < 0)
      .forEach(System.out::println);
}

它将像这样打印每对输出

You got 2 pairs
-----Pair----
-1
-2
-1
-2
-1
-----Pair----
-1