Как отсортировать список объектов в Java компаратором типа String?
Код создает объекты Test Result (имя строки, перечисление) с помощью цикла for и добавляет их в список, и я пытаюсь отсортировать их на основе их имен. Имена объектов должны быть примерно такими: Test1, Test2, ...Test200. Проблема связана с вышеуказанным Test9. Например, Test10 будет помещен между Test1 и Test2, а не после Test9. Или Test20 будет между Test2 и Test3.
Это мой код:
List<TestResult> testResultList = new ArrayList<>();
for (int i = 0; i < 100; i++)
{
testResultList.add(i, new TestResult(randomTestResultName(), TestStatus.randomEnumTestStatus()));
}
//method1 of sorting
testResultList.sort(Comparator.comparing(TestResult::getTestName));
//method2 of sorting
testResultList.sort((trl1, trl2)
-> trl1.getTestName().compareTo(
trl2.getTestName()));
и метод, который я использовал для создания случайных имен и перечислений:
private static String randomTestResultName() {
String t1="Test";
int randomNum = ThreadLocalRandom.current().nextInt(1, 10 + 1);
String t2 = Integer.toString(randomNum);
return t1+t2;
}
public static TestStatus randomEnumTestStatus() {
return TestStatus.values()[new Random().nextInt(TestStatus.values().length)];
}
ОБНОВЛЕНИЕ !: Для всех, у кого есть проблемы с строками с числами в конце, используйте этот метод, который вы будете использовать в качестве компаратора для сортировки с лямбда-выражением:
public static int compareNatural(String testResultName1, String testResultName2) {
int lengthOfTestResultName1 = testResultName1.length();
int lengthOfTestResultName2 = testResultName2.length();
int browseTestResultName1 = 0;
int browseTestResultName2 = 0;
while (true) {
if (browseTestResultName1 == lengthOfTestResultName1)
return browseTestResultName2 == lengthOfTestResultName2 ? 0 : -1;
if (browseTestResultName2 == lengthOfTestResultName2)
return 1;
if (testResultName1.charAt(browseTestResultName1) >= '0' && testResultName1.charAt(browseTestResultName1) <= '9' && testResultName2.charAt(browseTestResultName2) >= '0' && testResultName2.charAt(browseTestResultName2) <= '9') {
int na = 0;
int nb = 0;
while (browseTestResultName1 < lengthOfTestResultName1 && testResultName1.charAt(browseTestResultName1) == '0')
browseTestResultName1++;
while (browseTestResultName1 + na < lengthOfTestResultName1 && testResultName1.charAt(browseTestResultName1 + na) >= '0' && testResultName1.charAt(browseTestResultName1 + na) <= '9')
na++;
while (browseTestResultName2 < lengthOfTestResultName2 && testResultName2.charAt(browseTestResultName2) == '0')
browseTestResultName2++;
while (browseTestResultName2 + nb < lengthOfTestResultName2 && testResultName2.charAt(browseTestResultName2 + nb) >= '0' && testResultName2.charAt(browseTestResultName2 + nb) <= '9')
nb++;
if (na > nb)
return 1;
if (nb > na)
return -1;
if (browseTestResultName1 == lengthOfTestResultName1)
return browseTestResultName2 == lengthOfTestResultName2 ? 0 : -1;
if (browseTestResultName2 == lengthOfTestResultName2)
return 1;
}
if (testResultName1.charAt(browseTestResultName1) != testResultName2.charAt(browseTestResultName2))
return testResultName1.charAt(browseTestResultName1) - testResultName2.charAt(browseTestResultName2);
browseTestResultName1++;
browseTestResultName2++;
}
}
и новое лямбда-выражение для сортировки:
testResultList.sort((trl1, trl2)
-> compareNatural(trl1.getTestName(),trl2.getTestName()) );