2015-04-12 4 views
1

Следующие коды предназначены для экспорта древовидной структуры данных в Map<String, String>, так что с ними можно будет легче манипулировать позже. Но забавная вещь toString() метод работает безупречно, но toMap() метод получил один отсутствующий родитель A, ребенок B. У кого-нибудь есть идея?MapTreeStructure Export As Map

public static void main(String[] args) { 

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

     Map<String, String> myMap = tree.toMap(); 
     if (myMap != null) { 
      for (Map.Entry<String, String> entry : myMap.entrySet()) { 
       System.out.println("parent: " + entry.getKey() + ", child: " 
         + entry.getValue()); 
      } 
     } 

    } 

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

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

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

    @Override 
    public boolean remove(N node, boolean cascade) { 
     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) { 
     return nodeParent.get(node); 
    } 

    @Override 
    public List<N> getChildren(N node) { 
     List<N> children = new LinkedList<N>(); 
     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(); 
    } 

    @Override 
    public Map<String, String> toMap() { 
     Map<String, String> map = new HashMap<String, String>(); 
     dumpNodeToMap(map, null); 
     return map; 
    } 

    private void dumpNodeToMap(Map<String, String> map, N node) { 
     if (node != null) { 
      map.put((String) getParent(node), node.toString()); 
     } 
     for (N child : getChildren(node)) { 
      dumpNodeToMap(map, child); 
     } 
    } 

    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); 
     } 

    } 

Выход Подписчиков на консоли:

- A 
    - B 
    - C 
     - D 
- E 
    - F 

parent: null, child: E 
parent: A, child: C 
parent: C, child: D 
parent: E, child: F 

Для справки, эти два класса используемого интерфейса:

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

и

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

Где декларация спараметрированного типа 'n' для этого класса? – Bobulous

+0

Включенный класс интерфейса MutableTree и Tree. – d4v1dv00

ответ

1

Ваш toMap метод retu rns a a Map<String, String>, чей ключ является именем родительского элемента и значением которого является одиночный дочерний элемент. Это означает, что когда ключ «A» может быть сохранен только один дочерний элемент, и он устанавливается на последний дочерний элемент, который найден, в данном случае «C», переписывая запись для «A», которая указывала на «В».

Вместо ваш метод toMap должен возвращать Map<String, List<String>>, переводящий от каждого родительского узла, такие как «А», к List дочерних элементов, таких, как «B» и «C». Очевидно, это нормально, если List содержит только один дочерний элемент, но он должен быть списком, если имеется более одного ребенка.

Обычный шаблон для создания List элементов, а не один элемента выглядит следующим образом:

String parentNode = getParent(node).toString(); 
List<String> childElements = null; 
if(map.contains(parentNode) { 
    // List of child elements already exists, so get it from the Map. 
    childElements = map.get(parentNode); 
} else { 
    // List of child elements does not yet exist, so create a new List 
    // and add it to the Map. 
    childElements = new ArrayList<>(); 
    map.put(parentNode, childElements); 
} 
childElements.add(node.toString()); 
+0

Спасибо за пример кода, я переписал метод toMap(). Будет обновлено выше. – d4v1dv00

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