#java #sorting #comparator
#java #сортировка #компаратор
Вопрос:
У меня есть список объектов класса «Категория»:
public class Category {
private String originalId;
private Double ordinal;
private String sportId;
private String sportName;
private String type;
private String version;
}
И список объектов класса «League»:
public class League {
private String leagueName;
private String originalId;
private int rank;
public League(String name, String originalId, int rank) {
this.leagueName = name;
this.originalId = originalId;
this.rank = rank;
}
Эти классы описывают одни и те же объекты (поэтому значение поля «originalId» класса «Category» равно значению поля «originalId» класса «League»), но значения для них взяты из разных источников, поэтому они были разделены с самого начала
Что мне нужно сделать, так это отсортировать список «Категория» по значению поля «ранг» из класса «Лига»
Итак, логика сортировки должна быть следующей:
- Для каждого объекта «Category» я попытаюсь найти соответствующий объект «League», сравнивая их поле «originalId»
- если найден соответствующий объект, то возьмите значение поля «ранг» из объекта «Лига» и используйте его для сортировки списка объектов «Категории» по рангу
- если соответствующий объект не найден, то такой объект «Категории» должен быть перемещен в конец списка во время сортировки
Итак, компаратор должен быть таким:
public static Comparator<Category> byRank() {
return nullsLast(comparing(Category::getRankFromCorrespondingLeagueObject, nullsLast(naturalOrder())));
}
И вот тут я зашел в тупик, потому что для меня необычно использовать значение поля, взятое из другого объекта, для его использования при сортировке
Есть ли какой-нибудь простой хороший подход к этому?
Ответ №1:
Создайте карту League
рангов по originalId
, предоставьте ее вашему компаратору и используйте ее. Если вы ничего не можете найти на карте, установите use Integer .MIN_VALUE (или MAX_VALUE, в зависимости от того, какой способ вы хотите упорядочить). Это упорядочило бы его до конца результата. Что-то вроде (немного псевдокода):
public static Comparator<Category> byRank(Map<String, Integer> leagueRanks) {
return new Comparator<Category>() {
@Override
public int compare(Category o1, Category o2) {
return Integer.compare(leagueRanks.getOrDefault(o1.getOriginalId(), Integer.MAX_VALUE), leagueRanks.getOrDefault(o2.getOriginalId(), Integer.MAX_VALUE));
}
};
}
Для сбора League
рангов для сопоставления вы можете использовать что-то вроде этого:
Map<String, Integer> leagueRanks = leagues.stream().collect(Collectors.toMap(it -> it.getOriginalId(), it -> it.getRank()));