2017-05-25 229 views
2

如果可能在一個班輪中使用Java 8流彙總樹的節點,有可能嗎?使用Java 8 Streams彙總樹節點

這裏是一個節點類來解決,這是使用一個遞歸和總結節點,如以下代碼

public class Node 
{ 
private int nodeNum;  
ArrayList<Node> children = new ArrayList<>(); 

public Node(int num) 
{ 
    this.nodeNum = num; 
} 

public int getNodeNum() 
{ 
    return nodeNum; 
} 

public boolean addNode(Node node) 
{ 
    return children.add(node); 
} 

public ArrayList<Node> getNodes() 
{ 
    return this.children; 
} 
} 

正常方式。

int getNodeSum(Node node) 
{ 
    int total = 0; 

    if(node.children.isEmpty()) 
     return node.getNodeNum(); 
    else 
    { 
     for(Node tempNode:node.children) 
     { 
      total+= getNodeSum(tempNode); 
     } 
     return total+node.getNodeNum(); 
    } 
} 

我們可以使用流來概括眼前的子節點,但我沒有得到如何將深使用流做遞歸。 此代碼僅將問題解決到單個級別。有任何想法嗎?

total = list.stream().filter(Node -> node.children.isEmpty()).map(Node:: getNodeNum).reduce(node.getNodeNum(), (a,b) -> a+b); 

回答

3

解決您的問題的一種方法是將遞歸與Stream.flatMap一起使用。

首先,你需要下面的輔助方法添加到您的Node類:

public Stream<Node> allChildren() { 
    return Stream.concat(
     Stream.of(this), 
     this.children.stream().flatMap(Node::allChildren)); // recursion here 
} 

這會返回一個Stream<Node>的元素是此節點及其所有子節點。

然後,可以按如下方式重寫getNodeSum方法:

int getNodeSum(Node node) { 
    return node.allChildren() 
     .mapToInt(Node::getNodeNum) 
     .sum(); 
} 

這使用上述定義Node.allChildren方法與Stream.mapToIntIntStream.sum方法一起來計算總和。


或者,你可以在你的NodeFunction<Node, Stream<Node>> descendants屬性執行到位遞歸:

private Function<Node, Stream<Node>> descendants = 
    node -> Stream.concat(
     Stream.of(node), 
     node.children.stream() 
      .flatMap(this.descendants)); // recursion here: function invoked again 

這是一個遞歸lambda表達式,因爲你所定義的函數是在=標誌的兩側。這種lambda表達式僅允許作爲類的屬性,即不能將遞歸lambda表達式分配給局部變量。

public Stream<Node> allChildren() { 
    return descendants.apply(this); 
} 

最後,您getNodeSum方法的代碼可以等同於以前的版本:

int getNodeSum(Node node) { 
    return node.allChildren() 
     .mapToInt(Node::getNodeNum) 
     .sum(); 
} 

有了遞歸函數,可以按如下方式重寫allChildren方法注意:雖然這種方法可能對某些人有吸引力,但它可能有一些缺點,即現在每個Node類的實例都具有descendants屬性,儘管不需要二。你可以繞過這個,即通過使用這個遞歸函數的Tree類作爲屬性,並且Node是內部類(其中descendants屬性被移除)。

1

您需要添加節點類recusive方法,它西港島線是連接子流

public Stream<Node> recursiveConcat() { 
    return Stream.concat(
     Stream.of(this), 
     children.stream().flatMap(Node::recursiveConcat)); 
} 

然後做 -

root.recusiveConcat().mapToInt(Node::getNodeNum).sum() 

整個代碼

public class Node { 

    private int nodeNum; 
    ArrayList<Node> children = new ArrayList<>(); 

    public Node(int num) { 
     this.nodeNum = num; 
    } 

    public int getNodeNum() { 
     return nodeNum; 
    } 

    public boolean addNode(Node node) { 
     return children.add(node); 
    } 

    public ArrayList<Node> getNodes() { 
     return this.children; 
    } 

    public Stream<Node> recursiveConcat() { 
     return Stream.concat(
       Stream.of(this), 
       children.stream().flatMap(Node::recursiveConcat)); 
    } 
} 


Node root = new Node(1); 
Node node1 = new Node(2); 
Node node2 = new Node(3); 
Node node3 = new Node(4); 
node2.addNode(node3); 
node1.addNode(node2); 
root.addNode(node1); 
System.out.println(root.recursiveConcat().mapToInt(Node::getNodeNum).sum());