вместо источника в качестве List<String>
Я бы порекомендовал использовать его в качестве List<Set<String>>
например
List<Set<String>> setList = new ArrayList<>();
setList.add(new HashSet<>(Arrays.asList("a","b")));
setList.add(new HashSet<>(Arrays.asList("a","c")));
setList.add(new HashSet<>(Collections.singletonList("a")));
setList.add(new HashSet<>(Collections.singletonList("b")));
setList.add(new HashSet<>());
Затем примените следующий компаратор вместе с операцией отображения, чтобы получить ожидаемый результат:
List<String> result =
setList.stream()
.sorted(Comparator.comparing((Function<Set<String>, Boolean>) Set::isEmpty)
.thenComparing(s -> String.join("", s),
String.CASE_INSENSITIVE_ORDER))
.map(Object::toString)
.collect(Collectors.toList());
и это печатает:
[[a], [a, b], [a, c], [b], []]
обратите внимание, что в настоящее время результатом является список строк, где каждая строка является строковым представлением данного набора.однако, если вы хотите, чтобы результат был List<Set<String>>
, просто удалите приведенную выше операцию map
.
Редактировать:
Удалось получить решение, работающее на основепо вашей первоначальной идее ....
Итак, во-первых, вам нужен совершенно новый компаратор вместо просто (s1, s2) -> s1.compareToIgnoreCase(s2)
, так как этого будет недостаточно.
Учитывая ввод:
Set<String> set = new HashSet<>();
set.add("{}");
set.add("{a}");
set.add("{b}");
set.add("{a, b}");
set.add("{a, c}");
и следующий потоковый конвейер:
List<String> result = set.stream()
.map(s -> s.replaceAll("[^A-Za-z]+", ""))
.sorted(Comparator.comparing(String::isEmpty)
.thenComparing(String.CASE_INSENSITIVE_ORDER))
.map(s -> Arrays.stream(s.split(""))
.collect(Collectors.joining(", ", "{", "}")))
.collect(Collectors.toList());
Тогда мы получим результат:
[{a}, {a, b}, {a, c}, {b}, {}]