Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 群值序列_Java_Sorting_Lambda_Java 8_Java Stream - Fatal编程技术网

Java 群值序列

Java 群值序列,java,sorting,lambda,java-8,java-stream,Java,Sorting,Lambda,Java 8,Java Stream,我想知道是否有任何巧妙的方法可以使用新的流API来“分组”值序列 e、 g.将一系列整数拆分为整数组,每组为升序: IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2); IntFunction next = i -> i + 1; // DESIRED OUTPUT: [[1,2,3], [-1], [-1], [1,2], [1,2]] 不幸的是,流API不太适合处理涉及流元素上依赖操作的问题,如下面的问题 但是,您可以

我想知道是否有任何巧妙的方法可以使用新的流API来“分组”值序列

e、 g.将一系列整数拆分为整数组,每组为升序:

IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2);
IntFunction next = i -> i + 1;

// DESIRED OUTPUT: [[1,2,3], [-1], [-1], [1,2], [1,2]]

不幸的是,流API不太适合处理涉及流元素上依赖操作的问题,如下面的问题

但是,您可以为此使用库:

public static void main(String[] args) {
    IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2);
    IntUnaryOperator next = i -> i + 1;

    List<List<Integer>> result = 
        IntStreamEx.of(seq).boxed().groupRuns((i1, i2) -> next.applyAsInt(i1) == i2).toList();

    System.out.println(result); // prints "[[1, 2, 3], [-1], [-1], [1, 2], [1, 2]]"
}
publicstaticvoidmain(字符串[]args){
IntStream seq=IntStream.of(1,2,3,-1,-1,1,2,1,2);
下一个插管器=i->i+1;
列表结果=
IntStreamEx.of(seq).boxed().groupRuns((i1,i2)->next.applyAsInt(i1)==i2.toList();
System.out.println(结果);//打印“[[1,2,3]、-1]、-1]、[1,2]、[1,2]”
}

这将所有连续整数分组到一个
列表中,其中第二个整数等于应用于第一个整数的
next
函数。最后,此流被收集到
列表中

没有@Tunaki solution那么优雅,而是使用“纯”Java-8流:

IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2);

Deque<Deque<Integer>> r = new ArrayDeque<>(singleton(new ArrayDeque<>()));

seq.filter(i -> !r.getLast().isEmpty() && r.getLast().getLast() + 1 != i || !r.getLast().add(i))
            .forEach(i -> r.add(new ArrayDeque<>(singleton(i))));

System.out.println(r); // prints: [[1, 2, 3], [-1], [-1], [1, 2], [1, 2]]
IntStream seq=IntStream.of(1,2,3,-1,-1,1,1,2);
Deque r=new ArrayDeque(singleton(new ArrayDeque()));
seq.filter(i->!r.getLast().isEmpty()&&r.getLast().getLast()+1!=i||!r.getLast().add(i))
.forEach(i->r.add(新ArrayDeque(singleton(i)));
System.out.println(r);//打印:[[1,2,3],-1],-1],[1,2],[1,2]]

这里只是为了代码的优雅,我使用了
Deque
类来使用
getLast()
方法(对于
List
来说,它不会那么紧凑)。

如果您愿意操作内存中的数据结构,比如数组或列表,那么在标准Java8中只需几个步骤就可以做到这一点。这可以使用数组编程技术来完成,如我的。使用一些类似于中使用的巧妙条件,可以以一种简洁的方式处理边缘情况

关键的洞察是要认识到一个新的段(或组)从所需谓词未满足的每一点开始。也就是说,新段开始于
seq[i-1]+1!=seq[i]
。让我们在输入上运行
IntStream
,筛选此属性的索引,并将结果存储在某个数组
x

    int[] seq = { 1, 2, 3, -1, -1, 1, 2, 1, 2 };
    int[] x = IntStream.range(1, seq.length)
                       .filter(i -> seq[i-1] + 1 != seq[i])
                       .toArray();
导致

    [3, 4, 5, 7]
这仅为我们提供分段的内部边界。要获得段的起点和终点,我们需要固定第一段的起点和最后一段的终点。我们调整索引范围并向过滤器添加一些条件:

    int[] x = IntStream.rangeClosed(0, seq.length)
                       .filter(i -> i == 0 || i == seq.length ||
                                    seq[i-1] + 1 != seq[i])
                       .toArray();

    [0, 3, 4, 5, 7, 9]
现在,每个相邻的索引对都是原始数组的子范围。我们可以使用另一个流来提取这些子范围,从而得到所需的结果:

    int[][] result =
        IntStream.range(0, x.length - 1)
                 .mapToObj(i -> Arrays.copyOfRange(seq, x[i], x[i+1]))
                 .toArray(int[][]::new);

    [[1, 2, 3], [-1], [-1], [1, 2], [1, 2]]
这可以被提取到一个函数中,该函数本身接受一个“next”函数,该函数计算段中的下一个值。也就是说,对于任何元素,如果其右侧的元素与下一个函数的结果匹配,则元素位于同一段中;否则它是一个段边界。代码如下:

int[][] segments(int[] seq, IntUnaryOperator next) {
    int[] x = IntStream.rangeClosed(0, seq.length)
                       .filter(i -> i == 0 || i == seq.length ||
                               next.applyAsInt(seq[i-1]) != seq[i])
                       .toArray();

    return  IntStream.range(0, x.length - 1)
                     .mapToObj(i -> Arrays.copyOfRange(seq, x[i], x[i+1]))
                     .toArray(int[][]::new);
}
你可以这样称呼它:

    int[] seq = { 1, 2, 3, -1, -1, 1, 2, 1, 2 };
    System.out.println(Arrays.deepToString(segments(seq, i -> i + 1)));

    [[1, 2, 3], [-1], [-1], [1, 2], [1, 2]]
更改下一个函数允许以不同的方式拆分段。例如,要将数组拆分为相等值的段,可以执行以下操作:

    int[] seq = { 2, 2, 1, 3, 3, 1, 1, 1, 4, 4, 4 };
    System.out.println(Arrays.deepToString(segments(seq, i -> i)));

    [[2, 2], [1], [3, 3], [1, 1, 1], [4, 4, 4]]
使用像这样的下一个函数的困难在于,属于某个段的值的条件是有限的。如果提供一个与相邻值进行比较的谓词来测试它们是否在同一段中,那就更好了。如果我们愿意支付拳击费用,我们可以使用
BiPredicate

int[][] segments(int[] input, BiPredicate<Integer, Integer> pred) {
    int[] x = IntStream.rangeClosed(0, input.length)
                       .filter(i -> i == 0 || i == input.length ||
                               !pred.test(input[i-1], input[i]))
                       .toArray();

    return  IntStream.range(0, x.length - 1)
                     .mapToObj(i -> Arrays.copyOfRange(input, x[i], x[i+1]))
                     .toArray(int[][]::new);
}

这可以专门用于在两个
int
值上使用一个基本的双谓词,也可以推广为允许在任何类型的输入上使用任何类型的
BiPredicate

输出不应该是这样的:
[[1,2,3],-1],-1,1,2],[1,2]
?@Flown No,因为
1!=next.apply(-1)
Ah ok
next
是一个谓词。虽然没有您的想法那么优雅,但它确实可以用纯Java-8流来完成。谢谢!看起来StreamEx可以帮我省去很多麻烦!应该注意的是,这种解决方案滥用了API(特别是,传递给
谓词
。过滤器
必须是无状态的。因此,这个解决方案无法并行化。@TagirValeev可以是Tanuki的解决方案吗?是的,实际上,在大输入时,您可能会有加速。每个StreamEx功能都能正确地处理并行化,而且大多数功能实际上都能从并行化中获益。这是4核机器上基准测试和结果的要点。嗯,速度提升不是很显著,但仍然很显著。串行版本的工作速度与您的大致相同。
    int[] seq = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };
    System.out.println(Arrays.deepToString(segments(seq, (a, b) -> b > a)));

    [[3], [1, 4], [1, 5, 9], [2, 6], [5], [3]]