2014-10-02 2 views
4

Я хочу, чтобы преобразовать дерево в потоке Java8 узловКак преобразовать структуру дерева в потоке узлов в Java

Вот дерево узлов, хранящих которым данные могут быть выбраны

public class SelectTree<D> { 

    private D data; 

    private boolean selected = false; 

    private SelectTree<D> parent; 

    private final List<SelectTree<D>> children = new ArrayList<>(); 

    public SelectTree(D data, SelectTree<D> parent) { 
    this.data = data; 
    if (parent != null) { 
     this.parent = parent; 
     this.parent.getChildren().add(this) ; 
    } 
    } 

    public D getData() { 
    return data; 
    } 

    public void setData(D data) { 
    this.data = data; 
    } 

    public boolean isSelected() { 
    return selected; 
    } 

    public void setSelected(boolean selected) { 
    this.selected = selected; 
    } 

    public SelectTree<D> getParent() { 
    return parent; 
    } 

    public void setParent(SelectTree<D> parent) { 
    this.parent = parent; 
    } 

    public List<SelectTree<D>> getChildren() { 
    return children; 
    } 

    public boolean isRoot() { 
    return this.getParent() == null; 
    } 

    public boolean isLeaf() { 
    return this.getChildren() == null || this.getChildren().isEmpty(); 
    } 
} 

Я хочу, чтобы получить коллекцию выбранных данных я хочу сделать что-то вроде этого:

public static void main(String[] args) { 
    SelectTree<Integer> root = generateTree() ; 

    List<Integer> selectedData = root.stream() 
      .peek(node -> System.out.println(node.getData()+": "+node.isSelected())) 
      .filter(node-> node.isSelected()) 
      .map(node-> node.getData()) 
      .collect(Collectors.toList()) ; 

    System.out.println("\nselectedData="+selectedData); 
    } 

    private static SelectTree<Integer> generateTree() { 
    SelectTree<Integer> n1 = new SelectTree(1,null) ; 
    SelectTree<Integer> n11 = new SelectTree(11,n1) ; 
    SelectTree<Integer> n12 = new SelectTree(12,n1) ; 
    n12.setSelected(true); 
    SelectTree<Integer> n111 = new SelectTree(111,n11) ; 
    n111.setSelected(true) ; 
    SelectTree<Integer> n112 = new SelectTree(112,n11) ; 
    SelectTree<Integer> n121 = new SelectTree(121,n12) ; 
    SelectTree<Integer> n122 = new SelectTree(122,n12) ; 
    return n1 ; 
    } 

проблема заключалась в том, чтобы найти реализацию потока(), и я думаю, что я мог бы помочь некоторым люди, разделяющие мое решение, и я бы interst знать, если есть какие-то вопросы или лучший способ делать это

Сначала это было для primefaces TreeNode но обобщать проблему для всех видов дерева


Редактировать Я удалил древо абстрактного класса бесполезного для этого puporse для упрощения кода

+0

Возможный дубликат [на Java, как эффективно и элегантно потопить потомков узла дерева?] (Http://stackoverflow.com/questions/32749148/in-java-how-do-i-efficiently-and- элегантно-поток-а-дерево-узлы-потомки) –

ответ

5

Я нахожу эту реализацию потока() которым является ДФС обход дерева:

public class SelectTree<D> { 

    //... 

    public Stream<SelectTree<D>> stream() { 
    if (this.isLeaf()) { 
     return Stream.of(this); 
    } else { 
     return this.getChildren().stream() 
       .map(child -> child.stream()) 
       .reduce(Stream.of(this), (s1, s2) -> Stream.concat(s1, s2)); 
    } 
    } 
} 

Если вы не можете изменить реализацию дерева, как для primefaces TreeNode (org.primefaces.model.TreeNode) вы можете определить метод в другом классе:

public Stream<TreeNode> stream(TreeNode parentNode) { 
    if(parentNode.isLeaf()) { 
     return Stream.of(parentNode) ; 
    } else { 
     return parentNode.getChildren().stream() 
       .map(childNode -> stream(childNode)) 
       .reduce(Stream.of(parentNode), (s1, s2) -> Stream.concat(s1, s2)) ; 
    } 
    } 
5

Одно маленькое дополнение к kwisatz «s ответ.

Эта реализация:

this.getChildren().stream() 
     .map(SelectTree::stream) 
     .reduce(Stream.of(this), Stream::concat); 

будет более охотно, я. е. вся иерархия будет пройдена во время создания потока. Если hirarchy большой и, скажем, вы ищете для одного узла, соответствующего некоторый предикат, вы можете более ленивое поведение:

Stream.concat(Stream.of(this), 
       this.getChildren().stream().flatMap(SelectTree::stream)); 

В этом случае, только дети корневого узла будут извлекается во время создания потока, и поиск узла не обязательно приведет к обходу всей иерархии.

Оба подхода продемонстрируют порядок итераций DFS.

Смежные вопросы