[java] A가 a보다 먼저, B가 b보다 먼저 오는 방식으로 사용자 정의 정렬

다음과 같은 색상 목록이 있습니다.

핑크, 블루, 레드, 블루, 그레이, 그린, 퍼플, 블랙 … 등

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.


답변