void (@NotNull List<ChildInfo> added, boolean markAllChildrenLoaded, @NotNull BiConsumer<? super VirtualFile, ? super ChildInfo> callback) { if (added.size() <= 1) { for (int i = 0; i < added.size(); i++) { ChildInfo info = added.get(i); assert info.getId() > 0 : info; @SuppressWarnings("MagicConstant") @PersistentFS.Attributes int attributes = info.getFileAttributeFlags(); boolean isEmptyDirectory = info.getChildren() != null && info.getChildren().length == 0; synchronized (myData) { int[] oldIds = myData.myChildrenIds; if (ArrayUtil.indexOf(oldIds, info.getId()) < 0) { VirtualFileSystemEntry file = createChildImpl(info.getId(), info.getNameId(), attributes, isEmptyDirectory); addChild(file); callback.accept(file, info); } } } if (markAllChildrenLoaded) { setAllChildrenLoaded(); } return; } // when there are many children, it's cheaper to merge sorted lists just like in merge sort boolean isCaseSensitive = isCaseSensitive(); Comparator<ChildInfo> byName = (p1, p2) -> compareNames(p1.getName(), p2.getName(), isCaseSensitive); added.sort(byName); synchronized (myData) { int[] oldIds = myData.myChildrenIds; IntList mergedIds = new IntArrayList(oldIds.length + added.size()); VfsData vfsData = getVfsData(); List<ChildInfo> existingChildren = new AbstractList<>() { @Override public ChildInfo get(int index) { int id = oldIds[index]; assert id > 0 : id; int nameId = vfsData.getNameId(id); return new ChildInfoImpl(id, nameId, null, null, null/*irrelevant here*/); } @Override public int size() { return oldIds.length; } }; ContainerUtil.processSortedListsInOrder(existingChildren, added, byName, true, (nextInfo, mergeResult) -> { if (mergeResult != ContainerUtil.MergeResult.COPIED_FROM_LIST1) { assert nextInfo.getId() > 0 : nextInfo; @SuppressWarnings("MagicConstant") @PersistentFS.Attributes int attributes = nextInfo.getFileAttributeFlags(); boolean isEmptyDirectory = nextInfo.getChildren() != null && nextInfo.getChildren().length == 0; myData.removeAdoptedName(nextInfo.getName()); VirtualFileSystemEntry file = createChildImpl(nextInfo.getId(), nextInfo.getNameId(), attributes, isEmptyDirectory); callback.accept(file, nextInfo); } mergedIds.add(nextInfo.getId()); }); myData.myChildrenIds = mergedIds.toIntArray(); if (markAllChildrenLoaded) { setAllChildrenLoaded(); } assertConsistency(isCaseSensitive, added); } }