List<Movement> (@NotNull Collection<? extends Movement> explicitMoves, @NotNull Collection<? extends CommitChange> changes) { HashMultiset<FilePath> movedPathsMultiSet = HashMultiset.create(); for (Movement move : explicitMoves) { movedPathsMultiSet.add(move.getBefore()); movedPathsMultiSet.add(move.getAfter()); } HashMultiset<FilePath> beforePathsMultiSet = HashMultiset.create(); HashMultiset<FilePath> afterPathsMultiSet = HashMultiset.create(); for (CommitChange change : changes) { addIfNotNull(beforePathsMultiSet, change.beforePath); addIfNotNull(afterPathsMultiSet, change.afterPath); } return filter(explicitMoves, move -> movedPathsMultiSet.count(move.getBefore()) == 1 && movedPathsMultiSet.count(move.getAfter()) == 1 && beforePathsMultiSet.count(move.getBefore()) == 1 && afterPathsMultiSet.count(move.getAfter()) == 1 && beforePathsMultiSet.count(move.getAfter()) == 0 && afterPathsMultiSet.count(move.getBefore()) == 0); }