Java で List 要素の比較ではなく List 同士の比較をする方法を紹介します。
やりたいこと
リストの中身を辞書順のように比較するような compare メソッドがほしいと思いました。
以下のようになるイメージです。
// 素朴な比較
compare(List.of('a', 'p', 'p', 'l', 'e'), List.of('a', 'p', 'p')) > 0
compare(List.of('a', 'p', 'p'), List.of('a', 'p', 'p')) == 0
// Comparator を指定しての比較
compare(
List.of(JapaneseDate.of(JapaneseEra.REIWA, 5, 12, 25)),
List.of(LocalDate.of(2023, 12, 25)),
ChronoLocalDate.timeLineOrder()
) == 0
実装
public class Lists {
public static <T extends Comparable<? super T>> int compare(List<? extends T> list1, List<? extends T> list2) {
return compare(list1, list2, Comparator.naturalOrder());
}
public static <T> int compare(List<? extends T> list1, List<? extends T> list2, Comparator<? super T> comparator) {
int minSize = Math.min(list1.size(), list2.size());
for (int i = 0; i < minSize; i++) {
int compared = comparator.compare(list1.get(i), list2.get(i));
if (compared != 0)
return compared;
}
return list1.size() - list2.size();
}
}
使用例
public static void main(String[] args) {
SortedSet<List<String>> stringListSet = new TreeSet<>(Lists::compare);
stringListSet.add(List.of("pen", "pineapple", "apple", "pen"));
stringListSet.add(List.of("pan", "pancake"));
stringListSet.add(List.of("pan", "pancake", "almond", "potato"));
stringListSet.forEach(System.out::println);
// [pan, pancake]
// [pan, pancake, almond, potato]
// [pen, pineapple, apple, pen]
}