23

Java では、一部のフィールドを .xml にできるクラスを使用しますnull。例えば:

class Foo {
    String bar;
    //....
}

このクラスの BarComparator を書きたいのですが、

    private static class BarComparator
            implements Comparator<Foo> {
        public int compare( final Foo o1, final Foo o2 )
        {
            // Implementation goes here
        }
    }

ネストされた...をたくさん書くことなくo1o2o1.bar、のいずれかがo2.bar可能であるという事実に対処する標準的な方法はありますか?nullifelse

乾杯!

4

10 に答える 10

37

フィールドcompareToメソッドの呼び出しを小さな静的メソッドでラップして、nullを高または低にソートできると思います。

static <T extends Comparable<T>> int cp(T a, T b) {
     return
         a==null ?
         (b==null ? 0 : Integer.MIN_VALUE) :
         (b==null ? Integer.MAX_VALUE : a.compareTo(b));
}

簡単な使用法(複数のフィールドは通常どおりです):

public int compare( final Foo o1, final Foo o2 ) {
    return cp(o1.field, o2.field);
}
于 2008-09-24T16:30:06.103 に答える
8

返信ありがとうございます。一般的な方法と Google Comparators は興味深いものに見えます。

そして、Apache Commons Collections (現在使用している) にNullComparatorがあることがわかりました。

private static class BarComparator
        implements Comparator<Foo>
{
    public int compare( final Foo o1, final Foo o2 )
    {
        // o1.bar & o2.bar nulleness is taken care of by the NullComparator.
        // Easy to extend to more fields.
        return NULL_COMPARATOR.compare(o1.bar, o2.bar);
    }

    private final static NullComparator NULL_COMPARATOR =
                                            new NullComparator(false);
}

注:barここでは、要点を維持するためにフィールドに焦点を当てました。

于 2008-09-25T14:25:09.263 に答える
6

null エントリを比較に値する有効な文字列値と見なすかどうかによって異なります。null < または > "apple" です。確かに言えることは、null == null ということだけです。null が順序付けに適合する場所を定義できれば、コードを適切に記述できます。

この場合、NullPointerExcpetion または IllegalArgumentException をスローすることを選択し、最初から null を比較に入れずに、より高いレベルで null を処理しようとするかもしれません。

于 2008-09-24T16:12:05.707 に答える
3

Comparator を書くことができます。プライベート フィールドとして文字列名を持つクラス Person があるとします。getName() および setName() メソッドを使用してフィールド名にアクセスします。以下はクラス Person の Comparator です。

    Collections.sort(list, new Comparator<Person>() {
        @Override
        public int compare(Person a, Person b) {
            if (a == null) {
                if (b == null) {
                    return 0;
                }
                return -1;
            } else if (b == null) {
                return 1;
            }
            return a.getName().compareTo(b.getName());
        }
    });

アップデート:

Java 8 の時点で、以下の API を List に使用できます。

// Push nulls at the end of List
Collections.sort(subjects1, Comparator.nullsLast(String::compareTo));

// Push nulls at the beginning of List
Collections.sort(subjects1, Comparator.nullsFirst(String::compareTo));
于 2015-10-02T18:58:09.720 に答える
3

ここで重要なことは、null をどのように処理するかを決定することです。いくつかのオプションがあります: a) null はソート順で他のすべてのオブジェクトの前に来ると仮定する b) null はソート順で他のすべてのオブジェクトの後に来ると仮定する c) null を何らかのデフォルト値と同等のものとして扱う d) null をエラー条件として扱う。どちらを選択するかは、作業中のアプリケーションに完全に依存します。

もちろん、最後のケースでは例外をスローします。他のものについては、4 通りの if/else ケースが必要です (約 3 分間のコーディングで、結果をどうしたいかを理解できます)。

于 2008-09-24T17:17:45.410 に答える
3

Google コレクションを使用している場合は、Comparatorsクラスが役立つことがあります。null をコレクション内の最大または最小の要素として順序付けするためのヘルパー メソッドがある場合。複合コンパレータを使用して、コードの量を減らすことができます。

于 2008-09-24T18:54:21.230 に答える
1

NullComparator を自分のやり方で使用しないでください。比較操作ごとにクラスの新しいインスタンスを作成しています。たとえば、1000 エントリのリストをソートしている場合、それは 1000 * log2(1000) オブジェクトになります。は完全に不要です。これはすぐに問題になる可能性があります。

それをサブクラス化するか、デリゲートするか、または単に独自の null チェックを実装します。実際にはそれほど複雑ではありません。

private static class BarComparator
        implements Comparator<Foo> {
    private NullComparator delegate = new NullComparator(false);

    public int compare( final Foo o1, final Foo o2 )
    {
        return delegate.compare(o1.bar, o2.bar);
    }
}
于 2008-09-25T17:06:22.217 に答える
0

初期の return ステートメントは、多くの if の代替手段になると思います

例えば

if(o1==null) return x;
if(o2==null) return x;
if(o1.getBar()==null) return x;
if(o2.getBar()==null) return x;

// No null checks needed from this point.
于 2008-09-24T16:07:09.060 に答える