MapTreeStructure Экспорт как карта

1

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

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 для этого класса?
  • 0
    Включен интерфейс класса MutableTree и Tree.
Теги:
dictionary
tree

1 ответ

1
Лучший ответ

Метод toMap возвращает aa Map<String, String> чей ключ является именем родительского элемента и значением которого является один дочерний элемент. Это означает, что когда ключ "A" может быть сохранен только один дочерний элемент, и он устанавливается на последний дочерний элемент, который найден, в данном случае "C", переписывая запись для "A", которая указывала на "В".

Вместо этого ваш метод toMap должен вернуть Map<String, List<String>> который отображает из каждого родительского узла, такого как "A", в 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 (). Буду обновлять выше.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню