void (@NotNull TreePath path) { myPathsToProcessCollapseState.add(path); myCollapseStateAlarm.cancelAllRequests(); myCollapseStateAlarm.addRequest(() -> { // We assume that the paths collection is modified only from the EDT, so, ConcurrentModificationException doesn't have // a chance. // Another thing is that we sort the paths in order to process the longest first. That is related to the JTree specifics // that it automatically expands parent paths on child path expansion. List<TreePath> paths = new ArrayList<>(myPathsToProcessCollapseState); myPathsToProcessCollapseState.clear(); paths.sort(PATH_COMPARATOR); for (TreePath treePath : paths) { applyCollapseState(treePath); } final TreePath rootPath = new TreePath(getModel().getRoot()); if (isCollapsed(rootPath)) { expandPath(rootPath); } }, COLLAPSE_STATE_PROCESSING_DELAY_MILLIS); }