Comparable
コントラクトは、e.compareTo(null)
がNullPointerException
をスローする必要があることを指定します。
から API :
null
はどのクラスのインスタンスでもないことに注意してください。また、e.compareTo(null)
がNullPointerException
を返しても、e.equals(null)
はfalse
をスローする必要があります。
一方、 Comparator
API は、null
を比較するときに何が必要かについては何も言及していません。 Comparable
を取り、Comparator
を最小要素として配置するnull
を返すジェネリックメソッドの次の試みを考えてみてください。
static <T extends Comparable<? super T>> Comparator<T> nullComparableComparator() {
return new Comparator<T>() {
@Override public int compare(T el1, T el2) {
return
el1 == null ? -1 :
el2 == null ? +1 :
el1.compareTo(el2);
}
};
}
これにより、次のことが可能になります。
List<Integer> numbers = new ArrayList<Integer>(
Arrays.asList(3, 2, 1, null, null, 0)
);
Comparator<Integer> numbersComp = nullComparableComparator();
Collections.sort(numbers, numbersComp);
System.out.println(numbers);
// "[null, null, 0, 1, 2, 3]"
List<String> names = new ArrayList<String>(
Arrays.asList("Bob", null, "Alice", "Carol")
);
Comparator<String> namesComp = nullComparableComparator();
Collections.sort(names, namesComp);
System.out.println(names);
// "[null, Alice, Bob, Carol]"
したがって、質問は次のとおりです。
Comparator
の許容できる使用法ですか、それともnull
の比較とNullPointerException
のスローに関する不文律に違反していますか?List
要素を含むnull
をソートする必要があるのは良い考えですか、それとも設計エラーの確かな兆候ですか?Comparable
はnull
を許可しません。理由は次のとおりです。
_a.compareTo(b) == -b.compareTo(a)
_
すべてのオブジェクトに対してa
およびb
ここで、!a.equals(b)
。すなわち:
_a.equals(b) ? b.equals(a) && a.compareTo(b) == 0 &&
b.compareTo(a) == 0 && a.hashCode() == b.hashCode()
: !b.equals(a) && a.compareTo(b) != 0 &&
a.compareTo(b) == -b.compareTo(a)
_
関連する契約を満たすには、true
と評価する必要があります。
したがって、次のことができないため、null
は許可されません。
_null.compareTo(a)
_
Comparator
はより柔軟であるため、null
の処理は実装固有の問題です。 Comparator
に何をさせたいかに応じて、サポートするかどうかを指定します。
Null要素を含むリストをソートする必要があるのは良い考えですか、それとも設計エラーの確かな兆候ですか?
概念的には、nullは「何もない」ことを意味し、リストに何も配置しないことは私には奇妙に思えます。また、Javaリストコントラクトは次のように述べています
一部のリスト実装には、含めることができる要素に制限があります。たとえば、一部の実装ではnull要素が禁止されています
したがって、JavaのList実装は、null要素をサポートする必要すらありません。要約すると、nullをリストに入れる正当な理由がない場合は、しないでください。実行する場合は、実際に期待どおりに機能することをテストします。
Null要素を含むリストをソートする必要があるのは良い考えですか、それとも設計エラーの確かな兆候ですか?
リストにnullオブジェクトを含めることはおそらく意味がありませんが、リストに「ビジネスオブジェクト」が含まれている可能性があり、ビジネスオブジェクトのさまざまなプロパティで並べ替えることができます。一部のプロパティにはnullが含まれている場合があります。
これはコンパレータの許容可能な使用法ですか?
BeanComparator を使用すると、プロパティにnullが含まれている場合でも、ビジネスオブジェクト内のプロパティを並べ替えることができるため、Comparatorの許容可能な使用法であると言わざるを得ません。