Subato

Spliterator für Baumimplementierung (Zusatzaufgabe)

package name.panitz.util.tree;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.*;
import java.util.Spliterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class Tree<E> {
  final E element;
  final List<Tree<E>> children;
  private Tree<E> parent=null;
  
  
  public Tree<E> getParent() {
    return parent;
  }

  public void setParent(Tree<E> p) {
    if (null!=parent)throw new RuntimeException("Multiple assignment to parent node.");
    this.parent = p;
  }

  @SafeVarargs
  public Tree(E element, Tree<E>... children) {
    this.element = element;
    this.children = List.of(children);
    this.children.parallelStream().forEach(child->child.setParent(this));
  }

  public int size() {
    return
      children.parallelStream().reduce(0, (r,c)->c.size()+r,(x,y)->x+y)+1;
  }

  @Override
  public String toString() {
    return element.toString()+children.toString();
  }

  public MySplit getSpliterator(){
    return new MySplit();
  }
  private class MySplit implements Spliterator<E>{  

    List<Tree<E>> toDo = new ArrayList<>();

    MySplit(){
      toDo.add(Tree.this);
    }
    
    @Override
    public boolean tryAdvance(Consumer<? super E> action) {
      if (toDo.isEmpty()) return false;
      var current = toDo.get(0);
      toDo.remove(0);
      toDo.addAll(current.children);
      
      action.accept(current.element);
      
      return true;
    }
  
    @Override
    public Spliterator<E> trySplit() {
      var s = toDo.size();
      if (s==0 ) return null;
      if (s==1){
        var n0 = toDo.get(0);
        if (n0.children.size()==0) return null;
        toDo.remove(0);
	toDo.addAll(0,n0.children);
	toDo.add(0,new Tree<>(n0.element));
	return trySplit();
      }
      var r = toDo.get(0).getSpliterator();	
      toDo.remove(0);
      for (var i=1;i<s/2;i++){
        var n0 = toDo.get(0);	
        r.toDo.add(n0);
        toDo.remove(0);
      }
      return r;
    }
    @Override
    public long estimateSize() {
      return Long.MAX_VALUE;
    }
    @Override
    public int characteristics() {
      return 0;
    }
    
  }


  public Stream<E> stream(){return StreamSupport.stream(getSpliterator(), false);}
  public Stream<E> parallelStream(){return StreamSupport.stream(getSpliterator(), true);}

}