Java 8 - 在数组中查找领导者

Rah*_*hra 3 lambda functional-programming java-8

我正在尝试学习Java 8的功能,尤其是它的函数式编程方面.所以我试图解决一个问题:在数组中查找领导者 - 领导者是一个元素,它比数组中右边的所有元素都大.

例如:

输入数组:{98,23,54,12,20,7,27}

产出:领导者 - 27 54 98

现在,我已经使用通常的迭代方法解决了这个问题,如下所示.

private static void findLeaders(int[] array) {
        int currentLeader = array[array.length - 1];
        System.out.println(currentLeader);
        for(int i = array.length - 1; i >= 0; i--) {
            if(array[i] > currentLeader) {
                System.out.println(array[i]);
                currentLeader = array[i];
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

我尝试使用Java 8解决它,但除了编写这段代码之外我做不了多少,这又有编译错误:

Function<Integer, Integer> checkLeader = i ->  i > currentLeader ? i : currentLeader;
Run Code Online (Sandbox Code Playgroud)

错误:在封闭范围内定义的局部变量currentLeader必须是最终的或有效的最终

现在,我如何使用Java 8的功能解决相同的问题.

Fed*_*ner 5

传统的,强制性的方法对我来说似乎是最好的,既考虑了性能和可读性/易于维护.尽管如此,这是我尝试使用流和一些函数式编程:

List<Integer> leaders = IntStream.rangeClosed(1, array.length)
    .mapToObj(i -> array[array.length - i])
    .collect(toLeaders());
Run Code Online (Sandbox Code Playgroud)

在这里我创建一个1..n封闭的范围,然后,内mapToObj,转化指数1n - 1,索引2n - 2,等等.我立即使用这个转换后的索引来获取数组的相应元素,最后在自定义收集器的帮助下将其收集到一个列表中.toLeaders()辅助方法返回此自定义收集器:

private static Collector<Integer, ?, List<Integer>> toLeaders() {
    BiConsumer<List<Integer>, Integer> accumulator = (leaders, n) -> { 
        if (leaders.isEmpty() || n > leaders.get(leaders.size() - 1)) { 
            leaders.add(n);
        }
    };
    return Collector.of(ArrayList::new, accumulator, (leaders1, leaders2) -> {
        leaders2.forEach(n -> accumulator.accept(leaders1, n));
        return leaders1;
    });
}
Run Code Online (Sandbox Code Playgroud)

BiConsumer<List<Integer>, Integer> accumulator接受两个值:含有迄今为止发现的领导人的列表,并且从该流的元素.这将Biconsumer检查给定的数字是否为领导者,如果检查成功,则将该数字添加到给定的领导者列表中.

然后,使用这个累加器的收集器是通过Collector.of实用程序创建的,该实用程序还接受一个Supplier可变结构,该结构将保存领导者(这是ArrayList::new)和一个BinaryOperator合并器,负责合并先前创建的两个领导者列表(这仅在流并行时使用).该组合器使用先前声明的 accumulator双消音器.