UpdateResult<N> (@NotNull Entry<N> parent, List<? extends Pair<N, Boolean>> children) { List<Entry<N>> newChildren = new ArrayList<>(children == null ? 0 : children.size()); List<Entry<N>> oldChildren = parent.children; Map<Entry<N>, K> mapInserted = new IdentityHashMap<>(); Map<Entry<N>, K> mapContained = new IdentityHashMap<>(); if (children != null && !children.isEmpty()) { children.forEach(pair -> { if (pair == null || pair.first == null) { LOG.warn("MapBasedTree: ignore null node"); return; } K key = getKey(pair.first); if (key == null) return; Entry<N> entry = findEntry(key); if (entry == null) { entry = new Entry<>(parent, parent.node, pair.first, pair.second); mapInserted.put(entry, key); } else if (parent != entry.getParentPath()) { LOG.warn("MapBasedTree: ignore node that belongs to another parent"); return; } else { mapContained.put(entry, key); } entry.index = newChildren.size(); newChildren.add(entry); }); } parent.leaf = children == null; parent.children = guard(newChildren); parent.valid = true; List<Entry<N>> removed = oldChildren; List<Entry<N>> inserted = newChildren; List<Entry<N>> contained = null; if (!mapContained.isEmpty()) { if (oldChildren == null) { oldChildren = emptyList(); LOG.warn("MapBasedTree: unexpected state"); } removed = ContainerUtil.filter(oldChildren, entry -> !mapContained.containsKey(entry)); inserted = ContainerUtil.filter(newChildren, entry -> !mapContained.containsKey(entry)); contained = ContainerUtil.filter(newChildren, entry -> mapContained.containsKey(entry)); } removeChildren(parent, removed); mapInserted.forEach(this::insert); return new UpdateResult<>(removed, inserted, contained); }