web-dev-qa-db-ja.com

nullに関するComparableおよびComparator契約

Comparableコントラクトは、e.compareTo(null)NullPointerExceptionをスローする必要があることを指定します。

から API

nullはどのクラスのインスタンスでもないことに注意してください。また、e.compareTo(null)NullPointerExceptionを返しても、e.equals(null)falseをスローする必要があります。

一方、 Comparator AP​​I は、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をソートする必要があるのは良い考えですか、それとも設計エラーの確かな兆候ですか?
35

Comparablenullを許可しません。理由は次のとおりです。

_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に何をさせたいかに応じて、サポートするかどうかを指定します。

25
cletus

Null要素を含むリストをソートする必要があるのは良い考えですか、それとも設計エラーの確かな兆候ですか?

概念的には、nullは「何もない」ことを意味し、リストに何も配置しないことは私には奇妙に思えます。また、Javaリストコントラクトは次のように述べています

一部のリスト実装には、含めることができる要素に制限があります。たとえば、一部の実装ではnull要素が禁止されています

したがって、JavaのList実装は、null要素をサポートする必要すらありません。要約すると、nullをリストに入れる正当な理由がない場合は、しないでください。実行する場合は、実際に期待どおりに機能することをテストします。

8

Null要素を含むリストをソートする必要があるのは良い考えですか、それとも設計エラーの確かな兆候ですか?

リストにnullオブジェクトを含めることはおそらく意味がありませんが、リストに「ビジネスオブジェクト」が含まれている可能性があり、ビジネスオブジェクトのさまざまなプロパティで並べ替えることができます。一部のプロパティにはnullが含まれている場合があります。

これはコンパレータの許容可能な使用法ですか?

BeanComparator を使用すると、プロパティにnullが含まれている場合でも、ビジネスオブジェクト内のプロパティを並べ替えることができるため、Comparatorの許容可能な使用法であると言わざるを得ません。

4
camickr