当前位置:  开发笔记 > 编程语言 > 正文

Java 8函数样式用索引进行迭代

如何解决《Java8函数样式用索引进行迭代》经验,为你挑选了1个好方法。

我一直在练习java 8流和功能风格.有时我尝试使用流来解决一些编程难题.在这段时间里,我发现了一类我不知道如何用流来解决的任务,只有经典的方法.

这种任务的一个例子是:给定一个数字数组,找到元素的索引,它将使数组左边部分的总和低于零.例如,对于数组[1, 2, 3, -1, 3, -10, 9]答案将是5

我的第一个想法是使用,IntStream.generate(0, arr.length)...但后来我不知道如何累积值并同时意识到索引.

所以问题是:

有可能以某种方式在流上累积值然后进行有条件退出吗?

什么是并行执行?它不适合寻找我们需要了解元素顺序的索引的问题.

Alexis C... 5

我怀疑你的任务非常适合流.您正在寻找的是典型的扫描左操作,其本质上是顺序操作.

例如,想象一下管道中的以下元素:[1, 2, -4, 5].并行执行可以将其分成两个子部分即[1, 2][-4, 5].那你会用它们做什么?您不能独立概括他们,因为这将产量[3][1],然后你失去的事实1 + 2 - 4 < 0得到尊重.

因此,即使你编写了一个跟踪索引和总和的收集器,它也无法并行执行(我怀疑你甚至可以从中受益)但你可以想象这样的收集器可以顺序使用:

public static Collector indexSumLeft(int limit) {
        return Collector.of(
                () -> new int[]{-1, 0, 0},
                (arr, elem) -> {
                    if(arr[2] == 0) {
                        arr[1] += elem;
                        arr[0]++;
                    }
                    if(arr[1] < limit) {
                        arr[2] = 1;
                    }

                },
                (arr1, arr2) -> {throw new UnsupportedOperationException("Cannot run in parallel");},
                arr -> arr[0]

        );
    }

一个简单的用法:

int index = IntStream.of(arr).boxed().collect(indexSumLeft(0));

这仍将遍历管道的所有元素,因此效率不高.

Arrays.parallelPrefix如果数据源是数组,您也可以考虑使用它.只需计算其上的部分和,然后使用流来查找总和低于限制的第一个索引.

Arrays.parallelPrefix(arr, Integer::sum);
int index = IntStream.range(0, arr.length)
                     .filter(i -> arr[i] < limit)
                     .findFirst()
                     .orElse(-1);

这里也计算了所有的部分和(但是并行).

简而言之,我会使用一个简单的for循环.



1> Alexis C...:

我怀疑你的任务非常适合流.您正在寻找的是典型的扫描左操作,其本质上是顺序操作.

例如,想象一下管道中的以下元素:[1, 2, -4, 5].并行执行可以将其分成两个子部分即[1, 2][-4, 5].那你会用它们做什么?您不能独立概括他们,因为这将产量[3][1],然后你失去的事实1 + 2 - 4 < 0得到尊重.

因此,即使你编写了一个跟踪索引和总和的收集器,它也无法并行执行(我怀疑你甚至可以从中受益)但你可以想象这样的收集器可以顺序使用:

public static Collector indexSumLeft(int limit) {
        return Collector.of(
                () -> new int[]{-1, 0, 0},
                (arr, elem) -> {
                    if(arr[2] == 0) {
                        arr[1] += elem;
                        arr[0]++;
                    }
                    if(arr[1] < limit) {
                        arr[2] = 1;
                    }

                },
                (arr1, arr2) -> {throw new UnsupportedOperationException("Cannot run in parallel");},
                arr -> arr[0]

        );
    }

一个简单的用法:

int index = IntStream.of(arr).boxed().collect(indexSumLeft(0));

这仍将遍历管道的所有元素,因此效率不高.

Arrays.parallelPrefix如果数据源是数组,您也可以考虑使用它.只需计算其上的部分和,然后使用流来查找总和低于限制的第一个索引.

Arrays.parallelPrefix(arr, Integer::sum);
int index = IntStream.range(0, arr.length)
                     .filter(i -> arr[i] < limit)
                     .findFirst()
                     .orElse(-1);

这里也计算了所有的部分和(但是并行).

简而言之,我会使用一个简单的for循环.

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有