### Question:
SyntacticEquivalence { public static List<List<Tree>> findDuplicatedGroups(List<Tree> list) { return list.stream() .collect(Collectors.groupingBy(ComparableTree::new, LinkedHashMap::new, Collectors.toList())) .values().stream() .filter(group -> group.size() > 1) .collect(Collectors.toList()); } private  SyntacticEquivalence(); static boolean areEquivalent(@Nullable List<? extends Tree> first, @Nullable List<? extends Tree> second); static boolean areEquivalent(@Nullable Tree first, @Nullable Tree second); static String getUniqueIdentifier(IdentifierTree identifier); static List<List<Tree>> findDuplicatedGroups(List<Tree> list);  }### Answer:
@Test public void duplicateGroups() { Tree a1 = identifier("a"); Tree a2 = identifier("a"); Tree a3 = a1; Tree b1 = identifier("b"); assertThat(findDuplicatedGroups(Arrays.asList(a1, b1, a2, a3))).containsExactly(Arrays.asList(a1, a2, a3)); assertThat(findDuplicatedGroups(Arrays.asList(a1, b1, null))).isEmpty(); }