boolean (@NotNull NodeIterator it1, @NotNull NodeIterator it2) { final List<PsiElement> elements1 = new ArrayList<>(); final List<PsiElement> elements2 = new ArrayList<>(); while (it1.hasNext()) { final PsiElement element = it1.current(); if (element != null) { elements1.add(element); } it1.advance(); } while (it2.hasNext()) { final PsiElement element = it2.current(); if (element != null) { elements2.add(element); } it2.advance(); } if (elements1.size() != elements2.size()) { return false; } Int2ObjectMap<List<PsiElement>> hashToElement = new Int2ObjectOpenHashMap<>(elements1.size()); for (PsiElement element : elements1) { TreeHashResult result = myTreeHasher.hash(element, null, myNodeSpecificHasher); if (result != null) { hashToElement.computeIfAbsent(result.getHash(), __ -> new ArrayList<>()).add(element); } } for (PsiElement element : elements2) { TreeHashResult result = myTreeHasher.hash(element, null, myNodeSpecificHasher); if (result != null) { int hash = result.getHash(); List<PsiElement> list = hashToElement.get(hash); if (list == null) { return false; } boolean found = false; for (Iterator<PsiElement> it = list.iterator(); it.hasNext();) { if (match(element, it.next())) { it.remove(); found = true; } } if (!found) { return false; } if (list.size() == 0) { hashToElement.remove(hash); } } } return hashToElement.size() == 0; }