Java 排序结果以A、A、B、B的形式递增返回。。。在爪哇

Java 排序结果以A、A、B、B的形式递增返回。。。在爪哇,java,list,collections,comparator,comparable,Java,List,Collections,Comparator,Comparable,我想按name属性对列表进行排序 排序应该是升序,像A,A,B,B。。。在爪哇 如果有人能在这方面帮助我,那就太好了 比如说 package corejava.compare; import java.util.Comparator; public class FirstNameSorter implements Comparator<Employee>{ @Override public int compare(Employee o1, Employee

我想按name属性对列表进行排序

排序应该是升序,像A,A,B,B。。。在爪哇

如果有人能在这方面帮助我,那就太好了

比如说

package corejava.compare;

import java.util.Comparator;

public class FirstNameSorter implements Comparator<Employee>{

     @Override
     public int compare(Employee o1, Employee o2) {
         return o1.getFirstName().compareTo(o2.getFirstName());
     }
}
但是,我需要以下输出:

A
D
T
b
A
b
D
T

就像在评论中提到的@Zabuza一样,您想要的顺序几乎是不区分大小写的字母顺序,但不完全一样,因为您希望在大写和小写字符是同一个字母时将它们分组在一起

您可以通过简单地添加名字的小写字母并对其进行比较来实现这一点,如果小写字母的检查显示匹配,则使用单独的检查恢复为纯粹的词典顺序:

e、 g

公共类FirstNameSorter实现Comparator{
@凌驾
公共整数比较(员工o1、员工o2){
int precheck=o1.getFirstName().toLowerCase().compareTo(o2.getFirstName().toLowerCase());
返回precheck!=0?precheck:o1.getFirstName().compareTo(o2.getFirstName());
}
}

也许这对你有用:

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("A", "D", "a", "b", "B", "T");
        list.sort(comparator());
        System.out.println(list);
    }

    private static Comparator<? super String> comparator() {
        return (Comparator<String>) (leftString, rightString) -> {
            if (leftString.length() == rightString.length()) {
                for (int index = 0; index < leftString.length(); index++) {
                    final String leftChar = leftString.substring(index, index + 1);
                    final String rightChar = rightString.substring(index, index + 1);
                    if (!leftChar.equals(rightChar)) {
                        if (leftChar.toUpperCase().equals(rightChar.toUpperCase())) {
                            if (leftChar.equals(leftChar.toLowerCase()) && 
                                    rightChar.equals(rightChar.toUpperCase())) {
                                return 1;
                            } else {
                                return -1;
                            }
                        } else {
                            return leftChar.toUpperCase()
                                    .compareTo(rightChar.toUpperCase());
                        }
                    }
                }
                return 0;
            } else {
                return (leftString.length() > rightString.length()) ? -1 : +1;
            }
        };
    }
}
更新(错误修复): 问题
仅使用
caseinsensitivitythennaturalorder
的原始解决方案将
a
Aa
排序为
[a,Aa]
,而不是预期的
[Aa,a]

原因
String。不区分大小写的\u顺序
只考虑长度相同的字符串,如
a
a
aA
aA
,这是后面由
然后比较
比较器提供的表示词法顺序的条件。但是由于
a
Aa
具有不同的长度,因此它们不会按照将
Aa
置于
a
之前的词法顺序进行额外排序

解决方案
为了解决这个问题,我们可以创建Comparator,它将手动迭代两个字符串的“公共”索引,并使用前面创建的
caseinsensitivethenaturalorde
(来自下面的原始答案)比较它们对应的字符。通过比较单个字符,我们确信这些字符具有相同的长度,这将解决问题,让我们应用顺序
A

Comparator<String> myComparator = (s1, s2) -> {
    for (int i = 0; i < Math.min(s1.length(), s2.length()); i++) {
        int compare = caseInsensitiveThenNaturalOrder 
                .compare(s1.substring(i, i + 1), s2.substring(i, i + 1));
        if (compare != 0) return compare;
    }
    return Integer.compare(s1.length(), s2.length());
};

//DEMO:
String[] arr = {"a","A","aA","Aa","a","aA","bb","b","Bb","bB","aB"};
Arrays.sort(arr, myComparator);
System.out.println(Arrays.toString(arr));

//Output:
//[A, Aa, a, a, aA, aA, aB, Bb, b, bB, bb]
演示(支持波兰语字符):

输出:
[AB,AB,AB,Ą,ą,CC,CC,CC]

如果要根据通过
getFirstName
访问的属性对
Employee
实例集合进行排序,可以使用
caseinsensitivethenaturalorder
Comparator等

Collections.sort(employees, Comparator.comparing(Employee::getFirstName, caseInsensitiveThenNaturalOrder));
也可以写成

employees.sort(Comparator.comparing(Employee::getFirstName, caseInsensitiveThenNaturalOrder));

更新了问题如果结果是
A,A,b
而不是
A,A,b
,这有关系吗?大写字母应该总是在它对应的小写字母之前吗(比如A之前的A,B之前的B)?是的,大写字母应该首先像A,A,B,通过我们当前的比较器按字典进行比较,看,所以它显然不是你想要的。对于比较器,您需要更复杂的方法。例如,首先基于忽略大小写进行比较(例如,通过将所有内容小写)。如果这两个元素是相等的,那么就按字典顺序进行比较(因为它的顺序是大写字母优先于小写字母)。如果操作正确,比较器可能有1到3行,也可以使用新的现代方法创建。Employee e1=新员工(1,“Aa”,“dLastName”,34);员工e2=新员工(2,“b”,“姓名”,30);员工e3=新员工(3,“Bb”,“sLastName”,31);员工e4=新员工(4,“C”,“zLastName”,25);它给我的输出是Aa,b,Bb,C,但输出应该是Aa,Bb,b,CI希望大写字母应该放在第一位。员工e1=新员工(1,“Aa”,“dLastName”,34);员工e5=新员工(1,“a”,“dLastName”,34);员工e2=新员工(2,“b”,“姓名”,30);员工e3=新员工(3,“Bb”,“sLastName”,31);员工e4=新员工(4,“C”,“zLastName”,25);它给我输出a,Aa,b,Bb,C,但我想要输出Aa,a,Bb,b,C
Comparator<String> myComparator = (s1, s2) -> {
    for (int i = 0; i < Math.min(s1.length(), s2.length()); i++) {
        int compare = caseInsensitiveThenNaturalOrder 
                .compare(s1.substring(i, i + 1), s2.substring(i, i + 1));
        if (compare != 0) return compare;
    }
    return Integer.compare(s1.length(), s2.length());
};

//DEMO:
String[] arr = {"a","A","aA","Aa","a","aA","bb","b","Bb","bB","aB"};
Arrays.sort(arr, myComparator);
System.out.println(Arrays.toString(arr));

//Output:
//[A, Aa, a, a, aA, aA, aB, Bb, b, bB, bb]
Comparator<String> caseInsensitiveThenNaturalOrder = String
            .CASE_INSENSITIVE_ORDER
            .thenComparing(Comparator.naturalOrder());
Collator coll = Collator.getInstance(new Locale("pl", "PL")); //set locale of supported characters
coll.setStrength(Collator.PRIMARY);
Comparator<Object> caseInsensitiveThenNaturalOrder = coll
        .thenComparing((o1, o2) -> o1.toString().compareTo(o2.toString()));
String[] arr = {"cC","Cc","cc","CC", "ab","aB","Ab","AB", "ą", "Ą"};
Arrays.sort(arr, caseInsensitiveThenNaturalOrder);
System.out.println(Arrays.toString(arr));
Collections.sort(employees, Comparator.comparing(Employee::getFirstName, caseInsensitiveThenNaturalOrder));
employees.sort(Comparator.comparing(Employee::getFirstName, caseInsensitiveThenNaturalOrder));