@Test() void testCycleTrivial() { assertThrows(IllegalStateException.class, () -> TopologicalSort.sort(List.of(edge("A", "A")))); }
static List<Branch> sort(List<Edge> edges) { List<Edge> eCopy = new ArrayList<>(edges); List<Branch> result = new ArrayList<>(); while (!eCopy.isEmpty()) { Set<Branch> orphans = eCopy.stream() .map(e -> e.from) .filter(f -> eCopy.stream().map(e -> e.to).noneMatch(f::equals)) .collect(Collectors.toSet()); if (orphans.isEmpty()) { throw new IllegalStateException("Detected a cycle! " + edges); } orphans.forEach(o -> { result.add(o); eCopy.removeIf(e -> o.equals(e.from)); }); } edges.stream() .map(e -> e.to) .filter(f -> edges.stream().map(e -> e.from).noneMatch(f::equals)) .forEach(result::add); return result; }
TopologicalSort { static List<Branch> sort(List<Edge> edges) { List<Edge> eCopy = new ArrayList<>(edges); List<Branch> result = new ArrayList<>(); while (!eCopy.isEmpty()) { Set<Branch> orphans = eCopy.stream() .map(e -> e.from) .filter(f -> eCopy.stream().map(e -> e.to).noneMatch(f::equals)) .collect(Collectors.toSet()); if (orphans.isEmpty()) { throw new IllegalStateException("Detected a cycle! " + edges); } orphans.forEach(o -> { result.add(o); eCopy.removeIf(e -> o.equals(e.from)); }); } edges.stream() .map(e -> e.to) .filter(f -> edges.stream().map(e -> e.from).noneMatch(f::equals)) .forEach(result::add); return result; } }
TopologicalSort { static List<Branch> sort(List<Edge> edges) { List<Edge> eCopy = new ArrayList<>(edges); List<Branch> result = new ArrayList<>(); while (!eCopy.isEmpty()) { Set<Branch> orphans = eCopy.stream() .map(e -> e.from) .filter(f -> eCopy.stream().map(e -> e.to).noneMatch(f::equals)) .collect(Collectors.toSet()); if (orphans.isEmpty()) { throw new IllegalStateException("Detected a cycle! " + edges); } orphans.forEach(o -> { result.add(o); eCopy.removeIf(e -> o.equals(e.from)); }); } edges.stream() .map(e -> e.to) .filter(f -> edges.stream().map(e -> e.from).noneMatch(f::equals)) .forEach(result::add); return result; }  }
TopologicalSort { static List<Branch> sort(List<Edge> edges) { List<Edge> eCopy = new ArrayList<>(edges); List<Branch> result = new ArrayList<>(); while (!eCopy.isEmpty()) { Set<Branch> orphans = eCopy.stream() .map(e -> e.from) .filter(f -> eCopy.stream().map(e -> e.to).noneMatch(f::equals)) .collect(Collectors.toSet()); if (orphans.isEmpty()) { throw new IllegalStateException("Detected a cycle! " + edges); } orphans.forEach(o -> { result.add(o); eCopy.removeIf(e -> o.equals(e.from)); }); } edges.stream() .map(e -> e.to) .filter(f -> edges.stream().map(e -> e.from).noneMatch(f::equals)) .forEach(result::add); return result; }   }
TopologicalSort { static List<Branch> sort(List<Edge> edges) { List<Edge> eCopy = new ArrayList<>(edges); List<Branch> result = new ArrayList<>(); while (!eCopy.isEmpty()) { Set<Branch> orphans = eCopy.stream() .map(e -> e.from) .filter(f -> eCopy.stream().map(e -> e.to).noneMatch(f::equals)) .collect(Collectors.toSet()); if (orphans.isEmpty()) { throw new IllegalStateException("Detected a cycle! " + edges); } orphans.forEach(o -> { result.add(o); eCopy.removeIf(e -> o.equals(e.from)); }); } edges.stream() .map(e -> e.to) .filter(f -> edges.stream().map(e -> e.from).noneMatch(f::equals)) .forEach(result::add); return result; }    }