简体   繁体   English

递归方法的 Java 8 实现

[英]Java 8 implementation for recursive method

What is the correct way of using lambdas for a recursive method?将 lambda 用于递归方法的正确方法是什么? I have been trying to write a depth-first-search recursive function for a Graph .我一直在尝试为Graph编写一个深度优先搜索递归函数。 I have tried implementing the Lambda version, but not sure if my implementation is the correct way of using it in a recursive function.我曾尝试实现 Lambda 版本,但不确定我的实现是否是在递归函数中使用它的正确方法。

Outline of the code:代码概要:

a) Old fashioned way a) 老式的方式

private void depthFirstSearch(final Graph graph, final int sourceVertex){
    count++;
    marked[sourceVertex]= true;
    for(int vertex:graph.getAllVerticesConnectedTo(sourceVertex)){
        if(marked[vertex]!=true){
            edgeTo[vertex]=sourceVertex;
            depthFirstSearch(graph,vertex);
        }
    }
}

b) Java 8 Lambdas way: b) Java 8 Lambdas 方式:

private void depthFirstSearchJava8(final Graph graph, final int sourceVertex){
    count++;
    marked[sourceVertex]= true;
    StreamSupport.stream(graph.getAllVerticesConnectedTo(sourceVertex).spliterator(),false)
            .forEach(vertex -> {
                if(marked[vertex]!=true){
                    edgeTo[vertex]=sourceVertex;
                    depthFirstSearchJava8(graph,sourceVertex);
                }
            });
}

I have tried to write a lambda version as above but could not figure out the advantage it is providing as compared to the traditional way.我曾尝试编写如上所述的 lambda 版本,但无法弄清楚与传统方式相比它提供的优势。

Thanks谢谢

Just because lambdas exist, this doesn't mean you have to use them everywhere.仅仅因为 lambda 存在,这并不意味着您必须在任何地方使用它们。

You are looping over an iterable, without filtering or mapping or transforming anything (which are the typical use cases for lambdas).您正在遍历一个可迭代对象,而无需过滤、映射或转换任何内容(这是 lambda 的典型用例)。

The for loop does what you want in a one-liner. for循环在单行中执行您想要的操作。 Therefore, lambdas should not be used here.因此,此处不应使用 lambda。

That's because there is no advantage, at least not in this case.那是因为没有优势,至少在这种情况下没有优势。 Lambdas are useful when you want to create a small function to be used in just one place in the program, eg when passing the lambda as an argument for another function.当您想创建一个仅在程序中的一个地方使用的小函数时,Lambda 很有用,例如,当将 lambda 作为另一个函数的参数传递时。 If your lambda takes more than one line of code, you should reconsider the idea of using it.如果您的 lambda 超过一行代码,您应该重新考虑使用它的想法。

You could rewrite your depthFirstSearch method as follows:您可以按如下方式重写depthFirstSearch方法:

private void depthFirstSearchJava8(Graph graph, int sourceVertex){
    count++;
    marked[sourceVertex] = true;
    graph.getAllVerticesConnectedTo(sourceVertex).stream()
        .filter(vertex -> !marked[vertex])
        .peek(vertex -> edgeTo[vertex] = sourceVertex)
        .forEach(vertex -> depthFirstSearchJava8(graph, vertex));
}

This code assumes getAllVerticesConnectedTo() method returns a collection of integers.此代码假定getAllVerticesConnectedTo()方法返回整数集合。 If it returns an array of integers instead, then use the following code:如果它返回一个整数数组,则使用以下代码:

private void depthFirstSearchJava8(Graph graph, int sourceVertex){
    count++;
    marked[sourceVertex] = true;
    Arrays.stream(graph.getAllVerticesConnectedTo(sourceVertex))
        .filter(vertex -> !marked[vertex])
        .peek(vertex -> edgeTo[vertex] = sourceVertex)
        .forEach(vertex -> depthFirstSearchJava8(graph, vertex));
}

In the first solution, I've used the Collection.stream() method to get a stream of connected vertices, while in the second one, I've used the Arrays.stream() method.在第一个解决方案中,我使用了Collection.stream()方法来获取连接顶点的流,而在第二个解决方案中,我使用了Arrays.stream()方法。 Then, in both solutions, I've first used filter() to keep only non marked vertices and peek() to modify the edgeTo array.然后,在这两种解决方案中,我首先使用filter()仅保留未标记的顶点,并使用peek()修改edgeTo数组。 Finally, forEach() is used to terminate the stream by invoking depthFirstSearchJava8() method recursively.最后, forEach()用于通过递归调用depthFirstSearchJava8()方法来终止流。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM