다음과 같은 색상 목록이 있습니다.
핑크, 블루, 레드, 블루, 그레이, 그린, 퍼플, 블랙 … 등
List<String> listOfColors = Arrays.asList("Pink", "Blue", "Red", "blue", "Grey", "green", "purple", "black");
일부 과일 색상을 필터링하는 것과 같은 중간 작업이 있습니다. 이제 필터링 된 결과가 순서대로 정렬되도록 남겨 둡니다.
블루, 블랙, 블루, 그레이, 그린, 핑크, 퍼플, 레드
나는 시도했다 :
List<String> collect = listOfColors.stream().sorted(String::compareToIgnoreCase)
.collect(Collectors.toList());
예상대로 작동하지 않습니다.
출력은 다음과 같습니다.
블랙, 블루, 블루, 그린, 그레이, 핑크, 퍼플, 레드
나는 다음을 원한다.
블루, 블랙, 블루, 그레이, 그린, 핑크, 퍼플, 레드
답변
내 해결책은 방법을 사용하여 두 단계로 정렬을 사용하는 Comparator.thenComparing()
것입니다.
먼저 첫 번째 문자 무시 대소 문자만으로 문자열을 비교하십시오. 따라서 첫 문자가 같은 그룹 (어떤 경우에 상관없이)은 지금까지 분류되지 않은 상태로 남아 있습니다. 그런 다음 두 번째 단계에서 일반 알파벳 정렬을 적용하여 정렬되지 않은 하위 그룹을 정렬하십시오.
List<String> listOfColors = Arrays.asList("Pink", "Blue", "Red", "blue", "Grey", "green", "purple", "black");
Comparator<String> comparator = Comparator.comparing(s ->
Character.toLowerCase(s.charAt(0)));
listOfColors.sort(comparator.thenComparing(Comparator.naturalOrder()));
System.out.println(listOfColors);
어쩌면 여전히 최적화 될 수는 있지만 원하는 결과를 얻을 수 있습니다.
[Blue, black, blue, Grey, green, Pink, purple, Red]
답변
RuleBasedCollator 를 사용하여 고유 한 규칙을 정의 할 수 있습니다 .
맞춤 규칙의 예 :
String rules = "< c,C < b,B";
위의 규칙은 문자열을 비교할 때
C
대문자와 소문자가 모두 대문자와 소문자보다 먼저 나타나도록 디코딩됩니다B
.
String customRules = "<A<a<B<b<C<c<D<d<E<e<F<f<G<g<H<h<I<i<J<j<K<k<L<l<M<m<N<n<O<o<P<p<Q<q<R<r<S<s<T<t<U<u<V<v<X<x<Y<y<Z<z";
RuleBasedCollator myRuleBasedCollator = new RuleBasedCollator(customRules);
Collections.sort(listOfColors,myRuleBasedCollator);
System.out.println(listOfColors);
산출:
[Blue, black, blue, Grey, green, Pink, purple, Red]
편집 :customRules
직접 작성하는 대신 아래 코드를 사용하여 코드를 생성 할 수 있습니다.
String a = IntStream.range('a', 'z' + 1).mapToObj(c -> Character.toString((char) c))
.flatMap(ch -> Stream
.of("<", ch.toUpperCase(), "<", ch)).collect(Collectors.joining(""));
답변
먼저 각 문자에 대해 대소 문자를 구분하지 않는 비교를 수행 한 다음 일치하는 경우 각 문자에 대해 대소 문자를 구분하는 비교를 수행하는 방법이 필요합니다.
public static int compare(String s1, String s2)
{
int len, i;
if (s1.length()<s2.length()) {
len = s1.length();
} else {
len = s2.length();
}
for (i=0;i<len;i++) {
if (Character.toUpperCase(s1.charAt(i)) < Character.toUpperCase(s2.charAt(i))) {
return -1;
} else if (Character.toUpperCase(s1.charAt(i)) > Character.toUpperCase(s2.charAt(i))) {
return 1;
} else if (s1.charAt(i) < s2.charAt(i)) {
return -1;
} else if (s1.charAt(i) > s2.charAt(i)) {
return 1;
}
}
if (s1.length() < s2.length()) {
return -1;
} else if (s1.length() > s2.length()) {
return 1;
} else {
return 0;
}
}
그런 다음이 메소드를에 전달할 수 있습니다 Stream.sorted
.