Структура данных дерева Java?

Есть ли хорошая (стандартная Java) структура данных для представления дерева в Java?

В частности, мне нужно представить следующее:

  • Дерево в любом node может иметь произвольное количество детей
  • Каждый node (после корня) является просто строкой (чьи дети также являются строками)
  • Мне нужно иметь возможность получить все дочерние элементы (какой-то список или массив строк), учитывая входную строку, представляющую заданный node

Есть ли доступная структура для этого или мне нужно создать свои собственные (если бы такие предложения были бы полезны).

Ответ 1

Здесь:

public class Tree<T> {
    private Node<T> root;

    public Tree(T rootData) {
        root = new Node<T>();
        root.data = rootData;
        root.children = new ArrayList<Node<T>>();
    }

    public static class Node<T> {
        private T data;
        private Node<T> parent;
        private List<Node<T>> children;
    }
}

Это базовая древовидная структура, которая может использоваться для String или любого другого объекта. Довольно просто реализовать простые деревья, чтобы делать то, что вам нужно.

Все, что вам нужно добавить, это методы для добавления, удаления, перемещения и конструкторов. Node является основным строительным блоком Tree.

Ответ 2

Еще одна древовидная структура:

public class TreeNode<T> implements Iterable<TreeNode<T>> {

    T data;
    TreeNode<T> parent;
    List<TreeNode<T>> children;

    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<TreeNode<T>>();
    }

    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);
        childNode.parent = this;
        this.children.add(childNode);
        return childNode;
    }

    // other features ...

}

Использование образца:

TreeNode<String> root = new TreeNode<String>("root");
{
    TreeNode<String> node0 = root.addChild("node0");
    TreeNode<String> node1 = root.addChild("node1");
    TreeNode<String> node2 = root.addChild("node2");
    {
        TreeNode<String> node20 = node2.addChild(null);
        TreeNode<String> node21 = node2.addChild("node21");
        {
            TreeNode<String> node210 = node20.addChild("node210");
        }
    }
}

BONUS
Посмотрите на полноценное дерево с помощью:

  • итератора
  • поиск
  • Java/С#

https://github.com/gt4dev/yet-another-tree-structure

Ответ 3

В JDK реализована довольно хорошая древовидная структура.

Посмотрите javax.swing.tree, TreeModel и TreeNode. Они предназначены для использования с JTreePanel, но на самом деле это довольно хорошая реализация дерева, и нет ничего, что помешало бы вам использовать ее без интерфейса swing.

Обратите внимание, что с Java 9 вы можете не использовать эти классы, поскольку они не будут присутствовать в 'Compact profiles'.

Ответ 4

Как насчет этого?

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

/**
  * @author [email protected] (Yohann Coppel)
  * 
  * @param <T>
  *          Object type in the tree.
*/
public class Tree<T> {

  private T head;

  private ArrayList<Tree<T>> leafs = new ArrayList<Tree<T>>();

  private Tree<T> parent = null;

  private HashMap<T, Tree<T>> locate = new HashMap<T, Tree<T>>();

  public Tree(T head) {
    this.head = head;
    locate.put(head, this);
  }

  public void addLeaf(T root, T leaf) {
    if (locate.containsKey(root)) {
      locate.get(root).addLeaf(leaf);
    } else {
      addLeaf(root).addLeaf(leaf);
    }
  }

  public Tree<T> addLeaf(T leaf) {
    Tree<T> t = new Tree<T>(leaf);
    leafs.add(t);
    t.parent = this;
    t.locate = this.locate;
    locate.put(leaf, t);
    return t;
  }

  public Tree<T> setAsParent(T parentRoot) {
    Tree<T> t = new Tree<T>(parentRoot);
    t.leafs.add(this);
    this.parent = t;
    t.locate = this.locate;
    t.locate.put(head, this);
    t.locate.put(parentRoot, t);
    return t;
  }

  public T getHead() {
    return head;
  }

  public Tree<T> getTree(T element) {
    return locate.get(element);
  }

  public Tree<T> getParent() {
    return parent;
  }

  public Collection<T> getSuccessors(T root) {
    Collection<T> successors = new ArrayList<T>();
    Tree<T> tree = getTree(root);
    if (null != tree) {
      for (Tree<T> leaf : tree.leafs) {
        successors.add(leaf.head);
      }
    }
    return successors;
  }

  public Collection<Tree<T>> getSubTrees() {
    return leafs;
  }

  public static <T> Collection<T> getSuccessors(T of, Collection<Tree<T>> in) {
    for (Tree<T> tree : in) {
      if (tree.locate.containsKey(of)) {
        return tree.getSuccessors(of);
      }
    }
    return new ArrayList<T>();
  }

  @Override
  public String toString() {
    return printTree(0);
  }

  private static final int indent = 2;

  private String printTree(int increment) {
    String s = "";
    String inc = "";
    for (int i = 0; i < increment; ++i) {
      inc = inc + " ";
    }
    s = inc + head;
    for (Tree<T> child : leafs) {
      s += "\n" + child.printTree(increment + indent);
    }
    return s;
  }
}

Ответ 5

I написал небольшую библиотеку, которая обрабатывает общие деревья. Это намного легче, чем качели. У меня также есть проект maven.

Ответ 6

public class Tree {
    private List<Tree> leaves = new LinkedList<Tree>();
    private Tree parent = null;
    private String data;

    public Tree(String data, Tree parent) {
        this.data = data;
        this.parent = parent;
    }
}

Очевидно, вы можете добавлять утилиты для добавления/удаления дочерних элементов.

Ответ 7

Вы должны начать с определения того, что такое дерево (для домена), лучше всего это сделать сначала определив интерфейс. Не все древовидные структуры являются изменяемыми, возможность добавлять и удалять узлы должна быть дополнительной функцией, поэтому мы создаем дополнительный интерфейс для этого.

Нет необходимости создавать объекты узлов, которые содержат значения, на самом деле я вижу это как главный недостаток и издержки проектирования в большинстве реализаций дерева. Если вы посмотрите на Swing, TreeModel не содержит классов узлов (только DefaultTreeModel использует TreeNode), поскольку они на самом деле не нужны.

public interface Tree <N extends Serializable> extends Serializable {
    List<N> getRoots ();
    N getParent (N node);
    List<N> getChildren (N node);
}

Изменяемая древовидная структура (позволяет добавлять и удалять узлы):

public interface MutableTree <N extends Serializable> extends Tree<N> {
    boolean add (N parent, N node);
    boolean remove (N node, boolean cascade);
}

Учитывая эти интерфейсы, код, который использует деревья, не должен сильно заботиться о том, как реализовано дерево. Это позволяет использовать как общие, так и специализированные реализации, где вы реализуете дерево, делегируя функции другому API.

Пример: структура дерева файлов

public class FileTree implements Tree<File> {

    @Override
    public List<File> getRoots() {
        return Arrays.stream(File.listRoots()).collect(Collectors.toList());
    }

    @Override
    public File getParent(File node) {
        return node.getParentFile();
    }

    @Override
    public List<File> getChildren(File node) {
        if (node.isDirectory()) {
            File[] children = node.listFiles();
            if (children != null) {
                return Arrays.stream(children).collect(Collectors.toList());
            }
        }
        return Collections.emptyList();
    }
}

Пример: общая древовидная структура (основанная на родительских/дочерних отношениях):

public class MappedTreeStructure<N extends Serializable> implements MutableTree<N> {

    public static void main(String[] args) {

        MutableTree<String> tree = new MappedTreeStructure<>();
        tree.add("A", "B");
        tree.add("A", "C");
        tree.add("C", "D");
        tree.add("E", "A");
        System.out.println(tree);
    }

    private final Map<N, N> nodeParent = new HashMap<>();
    private final LinkedHashSet<N> nodeList = new LinkedHashSet<>();

    private void checkNotNull(N node, String parameterName) {
        if (node == null)
            throw new IllegalArgumentException(parameterName + " must not be null");
    }

    @Override
    public boolean add(N parent, N node) {
        checkNotNull(parent, "parent");
        checkNotNull(node, "node");

        // check for cycles
        N current = parent;
        do {
            if (node.equals(current)) {
                throw new IllegalArgumentException(" node must not be the same or an ancestor of the parent");
            }
        } while ((current = getParent(current)) != null);

        boolean added = nodeList.add(node);
        nodeList.add(parent);
        nodeParent.put(node, parent);
        return added;
    }

    @Override
    public boolean remove(N node, boolean cascade) {
        checkNotNull(node, "node");

        if (!nodeList.contains(node)) {
            return false;
        }
        if (cascade) {
            for (N child : getChildren(node)) {
                remove(child, true);
            }
        } else {
            for (N child : getChildren(node)) {
                nodeParent.remove(child);
            }
        }
        nodeList.remove(node);
        return true;
    }

    @Override
    public List<N> getRoots() {
        return getChildren(null);
    }

    @Override
    public N getParent(N node) {
        checkNotNull(node, "node");
        return nodeParent.get(node);
    }

    @Override
    public List<N> getChildren(N node) {
        List<N> children = new LinkedList<>();
        for (N n : nodeList) {
            N parent = nodeParent.get(n);
            if (node == null && parent == null) {
                children.add(n);
            } else if (node != null && parent != null && parent.equals(node)) {
                children.add(n);
            }
        }
        return children;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        dumpNodeStructure(builder, null, "- ");
        return builder.toString();
    }

    private void dumpNodeStructure(StringBuilder builder, N node, String prefix) {
        if (node != null) {
            builder.append(prefix);
            builder.append(node.toString());
            builder.append('\n');
            prefix = "  " + prefix;
        }
        for (N child : getChildren(node)) {
            dumpNodeStructure(builder, child, prefix);
        }
    }
}

Ответ 8

Вы можете использовать любой XML API Java в качестве документа и Node.. поскольку XML - это древовидная структура со строками

Ответ 9

В ответе нет более упрощенного, но действующего кода, так вот:

public class TreeNodeArray<T> {
    public T value;
    public final  java.util.List<TreeNodeArray<T>> kids =  new java.util.ArrayList<TreeNodeArray<T>>();
}

Ответ 10

В том же направлении, что и ответ Гарета, посмотрите DefaultMutableTreeNode. Это не общий, а, наоборот, похоже, соответствует законопроекту. Несмотря на то, что он находится в пакете javax.swing, он не зависит от каких-либо классов AWT или Swing. Фактически, исходный код на самом деле имеет комментарий // ISSUE: this class depends on nothing in AWT -- move to java.util?

Ответ 11

В Java существует несколько структур данных дерева, таких как DefaultMutableTreeNode в JDK Swing, Tree in the Stander parser package и другие коды игрушек. Но ни один из них не достаточно мал для общего назначения.

Java-tree пытается создать другую структуру данных древовидных данных общего назначения в Java. Разница между этим и другими:

  • Полностью бесплатный. Вы можете использовать его в любом месте (кроме вашей домашней работы: P)
  • Небольшой, но достаточно общий. Я помещал всю структуру данных в один файл класса, поэтому было бы легко скопировать/вставить.
  • Не только игрушки. Мне известны десятки кодов дерева Java, которые могут обрабатывать только двоичные деревья или ограниченные операции. Этот TreeNode намного больше. Он предоставляет различные способы посещения узлов, такие как предварительный заказ, постобработка, ширина, листья, путь к корню и т.д. Кроме того, итераторы предоставляются для достаточности.
  • Будет добавлено больше utils. Я готов добавить дополнительные операции, чтобы сделать этот проект всеобъемлющим, особенно если вы отправляете запрос через github.

Ответ 12

Если вы делаете кодировку в виде доски, интервью или даже планируете использовать дерево, многословие из них - это немного.

Далее следует сказать, что причина, по которой дерево не существует, например, Pair (о котором то же самое можно сказать), заключается в том, что вы должны инкапсулировать свои данные в класс, используя его, и простейшая реализация выглядит так:

/***
/* Within the class that using a binary tree for any reason. You could 
/* generalize with generics IFF the parent class needs different value types.
 */
private class Node {
  public String value;
  public Node[] nodes; // Or an Iterable<Node> nodes;
}

Это действительно для произвольного дерева ширины.

Если вам нужно бинарное дерево, оно часто проще использовать с именованными полями:

private class Node { // Using package visibility is an option
  String value;
  Node left;
  Node right;
}

Или, если вы хотите получить trie:

private class Node {
  String value;
  Map<char, Node> nodes;
}

Теперь вы сказали, что хотите

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

Это звучит как ваша домашняя работа.
Но поскольку я уверен, что какой-то крайний срок прошел...

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;

public class kidsOfMatchTheseDays {
 static private class Node {
   String value;
   Node[] nodes;
 }

 // Pre-order; you didn't specify.
 static public List<String> list(Node node, String find) {
   return list(node, find, new ArrayList<String>(), false);
 }

 static private ArrayList<String> list(
     Node node,
     String find,
     ArrayList<String> list,
     boolean add) {
   if (node == null) {
     return list;
   }
   if (node.value.equals(find)) {
     add = true;
   }
   if (add) {
     list.add(node.value);
   }
   if (node.nodes != null) {
     for (Node child: node.nodes) {
       list(child, find, list, add);
     }
   }
   return list;
 }

 public static final void main(String... args) {
   // Usually never have to do setup like this, so excuse the style
   // And it could be cleaner by adding a constructor like:
   //     Node(String val, Node... children) {
   //         value = val;
   //         nodes = children;
   //     }
   Node tree = new Node();
   tree.value = "root";
   Node[] n = {new Node(), new Node()};
   tree.nodes = n;
   tree.nodes[0].value = "leftish";
   tree.nodes[1].value = "rightish-leafy";
   Node[] nn = {new Node()};
   tree.nodes[0].nodes = nn;
   tree.nodes[0].nodes[0].value = "off-leftish-leaf";
   // Enough setup
   System.out.println(Arrays.toString(list(tree, args[0]).toArray()));
 }
}

Это поможет вам использовать:

$ java kidsOfMatchTheseDays leftish
[leftish, off-leftish-leaf]
$ java kidsOfMatchTheseDays root
[root, leftish, off-leftish-leaf, rightish-leafy]
$ java kidsOfMatchTheseDays rightish-leafy
[rightish-leafy]
$ java kidsOfMatchTheseDays a
[]

Ответ 13

Поскольку вопрос запрашивает доступную структуру данных, дерево может быть создано из списков или массивов:

Object[] tree = new Object[2];
tree[0] = "Hello";
{
  Object[] subtree = new Object[2];
  subtree[0] = "Goodbye";
  subtree[1] = "";
  tree[1] = subtree;
}

instanceof может использоваться, чтобы определить, является ли элемент поддеревом или терминалом node.

Ответ 14

public abstract class Node {
  List<Node> children;

  public List<Node> getChidren() {
    if (children == null) {
      children = new ArrayList<>();
    }
    return chidren;
  }
}

Проще, как он становится и очень прост в использовании. Чтобы использовать его, увеличьте его:

public class MenuItem extends Node {
  String label;
  String href;
  ...
}

Ответ 15

Например:

import java.util.ArrayList;
import java.util.List;



/**
 * 
 * @author X2
 *
 * @param <T>
 */
public class HisTree<T> 
{
    private Node<T> root;

    public HisTree(T rootData) 
    {
        root = new Node<T>();
        root.setData(rootData);
        root.setChildren(new ArrayList<Node<T>>());
    }

}

class Node<T> 
{

    private T data;
    private Node<T> parent;
    private List<Node<T>> children;

    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public Node<T> getParent() {
        return parent;
    }
    public void setParent(Node<T> parent) {
        this.parent = parent;
    }
    public List<Node<T>> getChildren() {
        return children;
    }
    public void setChildren(List<Node<T>> children) {
        this.children = children;
    }
}

Ответ 16

Я написал небольшой класс "TreeMap" на основе "HashMap", который поддерживает добавление путей:

import java.util.HashMap;
import java.util.LinkedList;

public class TreeMap<T> extends LinkedHashMap<T, TreeMap<T>> {

    public void put(T[] path) {
        LinkedList<T> list = new LinkedList<>();
        for (T key : path) {
            list.add(key);
        }
        return put(list);
    }

    public void put(LinkedList<T> path) {
        if (path.isEmpty()) {
            return;
        }
        T key = path.removeFirst();
        TreeMap<T> val = get(key);
        if (val == null) {
            val = new TreeMap<>();
            put(key, val);
        }
        val.put(path);
    }

}

Может использоваться для хранения дерева вещей типа "T" (общий), но пока не поддерживает хранение дополнительных данных в нем. Если у вас есть такой файл:

root, child 1
root, child 1, child 1a
root, child 1, child 1b
root, child 2
root, child 3, child 3a

Затем вы можете сделать это деревом, выполнив:

TreeMap<String> root = new TreeMap<>();
Scanner scanner = new Scanner(new File("input.txt"));
while (scanner.hasNextLine()) {
  root.put(scanner.nextLine().split(", "));
}

И вы получите красивое дерево. Он должен быть легко адаптирован к вашим потребностям.

Ответ 17

Вы можете использовать класс HashTree, включенный в Apache JMeter, который является частью проекта Jakarta.

Класс HashTree включен в пакет org.apache.jorphan.collections. Хотя этот пакет не выпущен вне проекта JMeter, вы можете легко его получить:

1) Загрузите источники JMeter.

2) Создайте новый пакет.

3) Скопируйте на него /src/jorphan/org/apache/jorphan/collections/. Все файлы, кроме Data.java

4) Скопируйте также /src/jorphan/org/apache/jorphan/util/JOrphanUtils.java

5) HashTree готов к использованию.

Ответ 18

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

package com.datastructure.tree;

public class BinaryTreeWithoutRecursion <T> {

    private TreeNode<T> root;


    public BinaryTreeWithoutRecursion (){
        root = null;
    }


    public void insert(T data){
        root =insert(root, data);

    }

    public TreeNode<T>  insert(TreeNode<T> node, T data ){

        TreeNode<T> newNode = new TreeNode<>();
        newNode.data = data;
        newNode.right = newNode.left = null;

        if(node==null){
            node = newNode;
            return node;
        }
        Queue<TreeNode<T>> queue = new Queue<TreeNode<T>>();
        queue.enque(node);
        while(!queue.isEmpty()){

            TreeNode<T> temp= queue.deque();
            if(temp.left!=null){
                queue.enque(temp.left);
            }else
            {
                temp.left = newNode;

                queue =null;
                return node;
            }
            if(temp.right!=null){
                queue.enque(temp.right);
            }else
            {
                temp.right = newNode;
                queue =null;
                return node;
            }
        }
        queue=null;
        return node; 


    }

    public void inOrderPrint(TreeNode<T> root){
        if(root!=null){

            inOrderPrint(root.left);
            System.out.println(root.data);
            inOrderPrint(root.right);
        }

    }

    public void postOrderPrint(TreeNode<T> root){
        if(root!=null){

            postOrderPrint(root.left);

            postOrderPrint(root.right);
            System.out.println(root.data);
        }

    }

    public void preOrderPrint(){
        preOrderPrint(root);
    }


    public void inOrderPrint(){
        inOrderPrint(root);
    }

    public void postOrderPrint(){
        inOrderPrint(root);
    }


    public void preOrderPrint(TreeNode<T> root){
        if(root!=null){
            System.out.println(root.data);
            preOrderPrint(root.left);
            preOrderPrint(root.right);
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BinaryTreeWithoutRecursion <Integer> ls=  new BinaryTreeWithoutRecursion <>();
        ls.insert(1);
        ls.insert(2);
        ls.insert(3);
        ls.insert(4);
        ls.insert(5);
        ls.insert(6);
        ls.insert(7);
        //ls.preOrderPrint();
        ls.inOrderPrint();
        //ls.postOrderPrint();

    }

}

Ответ 19

Custom Tree Tree дерева без использования рамки Collection. Он содержит различные фундаментальные операции, необходимые для реализации дерева.

class Node {

    int data;
    Node left;
    Node right;

    public Node(int ddata, Node left, Node right) {
        this.data = ddata;
        this.left = null;
        this.right = null;      
    }

    public void displayNode(Node n) {
        System.out.print(n.data + " "); 
    }

}

class BinaryTree {

    Node root;

    public BinaryTree() {
        this.root = null;
    }

    public void insertLeft(int parent, int leftvalue ) {
        Node n = find(root, parent);
        Node leftchild = new Node(leftvalue, null, null);
        n.left = leftchild;
    }

    public void insertRight(int parent, int rightvalue) {
        Node n = find(root, parent);
        Node rightchild = new Node(rightvalue, null, null);
        n.right = rightchild;
    }

    public void insertRoot(int data) {
        root = new Node(data, null, null);
    }

    public Node getRoot() {
        return root;
    }

    public Node find(Node n, int key) {     
        Node result = null;

        if (n == null)
            return null;

        if (n.data == key)
            return n;

        if (n.left != null)
            result = find(n.left, key);

        if (result == null)
            result = find(n.right, key);

        return result;
    } 

    public int getheight(Node root){
        if (root == null)
            return 0;

        return Math.max(getheight(root.left), getheight(root.right)) + 1; 
    }

    public void printTree(Node n) {     
        if (n == null)
            return;

        printTree(n.left);
        n.displayNode(n);
        printTree(n.right);             
    }

}

Ответ 20

В Java нет конкретной структуры данных, которая соответствует вашим требованиям. Ваши требования весьма специфичны, и для этого вам необходимо создать собственную структуру данных. Рассматривая ваши требования, каждый может сказать, что вам нужно какое-то n-арное дерево с определенной функциональностью. Вы можете сконструировать свою структуру данных следующим образом:

  • Структура node дерева будет похожа на содержимое в node и список дочерних элементов: class node {Строковое значение; Список детей;}
  • Вам нужно получить детей данной строки, поэтому вы можете иметь 2 метода 1: node searchNode (String str), вернет node, который имеет то же значение, что и заданный ввод (используйте BFS для поиска ) 2: Список getChildren (String str): этот метод будет внутренне вызывать searchNode, чтобы получить node с той же строкой, а затем создаст список всех строковых значений дочерних элементов и возвращает.
  • Вам также потребуется вставить строку в дерево. Вам нужно будет написать один метод: void insert (String parent, String value): это снова будет искать значение node, равное родительскому, и затем вы можете создать node с заданным значением и добавить в список детей к найденному родителю.

Я бы предположил, что вы пишете структуру node в одном классе, например Class node {String value; Список children;} и все другие методы, такие как search, insert и getChildren в другом классе NodeUtils, чтобы вы могли также передать корень дерева для выполнения операции над конкретным деревом: class NodeUtils {public static node search (Node root, String value) {//выполнить BFS и вернуть Node}

Ответ 21

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

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by kic on 16.07.15.
 */
public class NestedMap<K, V> {
    private final Map root = new HashMap<>();

    public NestedMap<K, V> put(K key) {
        Object nested = root.get(key);

        if (nested == null || !(nested instanceof NestedMap)) root.put(key, nested = new NestedMap<>());
        return (NestedMap<K, V>) nested;
    }

    public Map.Entry<K,V > put(K key, V value) {
        root.put(key, value);

        return (Map.Entry<K, V>) root.entrySet().stream().filter(e -> ((Map.Entry) e).getKey().equals(key)).findFirst().get();
    }

    public NestedMap<K, V> get(K key) {
        return (NestedMap<K, V>) root.get(key);
    }

    public V getValue(K key) {
        return (V) root.get(key);
    }

    @JsonValue
    public Map getRoot() {
        return root;
    }

    public static void main(String[] args) throws Exception {
        NestedMap<String, Integer> test = new NestedMap<>();
        test.put("a").put("b").put("c", 12);
        Map.Entry<String, Integer> foo = test.put("a").put("b").put("d", 12);
        test.put("b", 14);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(test));

        foo.setValue(99);
        System.out.println(mapper.writeValueAsString(test));

        System.out.println(test.get("a").get("b").getValue("d"));
    }
}

Ответ 22

    // TestTree.java
// A simple test to see how we can build a tree and populate it
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;

public class TestTree extends JFrame {

  JTree tree;
  DefaultTreeModel treeModel;

  public TestTree( ) {
    super("Tree Test Example");
    setSize(400, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public void init( ) {
    // Build up a bunch of TreeNodes. We use DefaultMutableTreeNode because the
    // DefaultTreeModel can use it to build a complete tree.
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode subroot = new DefaultMutableTreeNode("SubRoot");
    DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("Leaf 1");
    DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("Leaf 2");

    // Build our tree model starting at the root node, and then make a JTree out
    // of it.
    treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);

    // Build the tree up from the nodes we created.
    treeModel.insertNodeInto(subroot, root, 0);
    // Or, more succinctly:
    subroot.add(leaf1);
    root.add(leaf2);

    // Display it.
    getContentPane( ).add(tree, BorderLayout.CENTER);
  }

  public static void main(String args[]) {
    TestTree tt = new TestTree( );
    tt.init( );
    tt.setVisible(true);
  }
}

Ответ 23

Я написал библиотеку деревьев, которая отлично сочетается с Java8 и не имеет других зависимостей. Он также обеспечивает свободную интерпретацию некоторых идей из функционального программирования и позволяет вам отображать/фильтровать/обрезать/искать все дерево или поддеревья.

https://github.com/RutledgePaulV/prune

Реализация не делает ничего особенного с индексированием, и я не отклонялся от рекурсии, поэтому возможно, что с большими деревьями производительность ухудшится, и вы сможете взорвать стек. Но если все, что вам нужно, - это простое дерево с небольшой до средней глубиной, я думаю, что он работает достаточно хорошо. Он обеспечивает разумное (основанное на значении) определение равенства, а также имеет реализацию toString, которая позволяет визуализировать дерево!

Ответ 24

Вы можете использовать класс TreeSet в java.util. *. Он работает как дерево двоичного поиска, поэтому он уже отсортирован. Класс TreeSet реализует интерфейсы Iterable, Collection и Set. Вы можете проходить через дерево с помощью итератора, как набор.

TreeSet<String> treeSet = new TreeSet<String>();
Iterator<String> it  = treeSet.Iterator();
while(it.hasNext()){
...
}

Вы можете проверить Java Doc и некоторые другие.