Ваша первая попытка была не слишком плохой, но вам нужно добавить еще одно сравнение в случае аналогичных значений без учета регистра, чтобы упорядочить их:
Stream.of("sherin", "Sherin", "SHERIN", "bubBle", "buBble", "BUBBLE", "heart", "hEart", "hEArt")
.sorted((s1, s2) -> {
int tmp = s1.compareToIgnoreCase(s2);
return tmp == 0 ?
s1.compareTo(s2) //Compare equivalent values based on the case (upper case first)
: tmp;
}).forEach(System.out::println);
Компаратор, предоставленный для Stream.sorted
, аналогичен вашей реализации, но использует лямбда-нотацию.
Результат:
BUBBLE
buBble
bubBle
hEArt
hEart
heart
SHERIN
Sherin
sherin
РЕДАКТИРОВАТЬ: Спасибо Joop Eggen за предложение использовать декоратор компаратора:
Comparator
.comparing(Function.identity(), String::compareToIgnoreCase)
.thenComparing(Function.identity(), String::compareTo);
Это немного чище для использования и дает тот же результат:
Stream.of("sherin", "Sherin", "SHERIN", "bubBle", "buBble", "BUBBLE", "heart", "hEart", "hEArt").sorted(
Comparator
.comparing(Function.identity(), String::compareToIgnoreCase)
.thenComparing(Function.identity(), String::compareTo)
).forEach(System.out::println);
И короче, что я мог сделать с этим обозначением:
Comparator.comparing((String s) ->.toLowerCase()).thenComparing(Function.identity())