Frage

In Java verwende ich eine Klasse, in der einige Felder sein können null. Zum Beispiel:

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

Ich möchte für diese Klasse einen Barcomparator schreiben,

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

Gibt es eine Standardmethode, um mit der Tatsache umzugehen, dass einer von einem von o1, o2, o1.bar, o2.bar kann sein null, ohne viel verschachtelt zu schreiben if...else?

Prost!

War es hilfreich?

Lösung

Ich denke, Sie könnten den Aufruf auf die Feldvergleichsmethode mit einer kleinen statischen Methode einwickeln, um Nulls hoch oder niedrig zu sortieren:

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));
}

Einfache Verwendung (mehrere Felder sind wie gewohnt):

public int compare( final Foo o1, final Foo o2 ) {
    return cp(o1.field, o2.field);
}

Andere Tipps

Danke für die Antworten! Die generische Methode und die Google -Komparatoren sehen interessant aus.

Und ich fand, dass es eine gibt NULLCOMPARATOR in dem Apache Commons -Sammlungen (was wir derzeit verwenden):

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);
}

Hinweis: Ich habe mich auf die konzentriert bar Feld hier, um es auf den Punkt zu halten.

Dies hängt davon ab, ob Sie einen Nulleintrag als einen gültigen Vergleich im Wert von String betrachten. ist null <oder> "Apple". Das einzige, was ich mit Sicherheit sagen könnte, ist, dass null == null. Wenn Sie definieren können, wo Null in die Bestellung passt, können Sie den Code entsprechend schreiben.

In diesem Fall könnte ich mich entscheiden, einen Nullpointerexcetion oder illegalArgumentException zu werfen und zu versuchen, die Null auf einer höheren Ebene zu bewältigen, indem sie ihn nicht in erster Linie vergleichbar machen.

Sie können Ihren Komparator dafür schreiben. Nehmen wir an, Sie haben eine Klassenperson mit Zeichenfolgennamen als privates Feld. GetName () und setName () -Methode, um auf den Feldnamen zuzugreifen. Unten ist der Vergleich für die Klassenperson.

    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());
        }
    });

Aktualisieren:

Ab Java 8 können Sie unten APIs für die Liste verwenden.

// 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));

Das Wichtigste hier ist, herauszufinden, wie Nulls behandelt werden sollen. Einige Optionen sind: a) Angenommen, Nulls kommen vor allen anderen Objekten in sortierender Reihenfolge b) Angenommen, Nulls kommen nach allen anderen Objekten in Sortierreihenfolge c) Null als äquivalent zu einem Standardwert d) Nulls als Fehlerbedingungen behandeln. An welchen Sie wählen, hängt vollständig von der Anwendung ab, an der Sie arbeiten.

Im letzten Fall machen Sie natürlich eine Ausnahme. Für die anderen benötigen Sie einen Vier-Wege, wenn/sonst der Fall (etwa drei Minuten Codierung, Sie haben herausgefunden, was die Ergebnisse sein sollen).

Wenn Sie Google -Sammlungen verwenden, finden Sie möglicherweise das Komparatoren Klasse hilfreich. Wenn Helfermethoden zur Bestellung von Nulls als die größten oder am wenigsten Elemente in der Sammlung bestellt werden. Sie können verwenden zusammengesetzte Komparatoren Um die Menge an Code zu reduzieren.

Es gibt auch die Klasse org.springframework.util.comparator.NullSafeComparator Im Spring -Framework können Sie verwenden.

Beispiel (Java 8):

SortedSet<Foo> foos = new TreeSet<>( ( o1, o2 ) -> {
        return new NullSafeComparator<>( String::compareTo, true ).compare( o1.getBar(), o2.getBar() );
    } );

    foos.add( new Foo(null) );
    foos.add( new Foo("zzz") );
    foos.add( new Foo("aaa") );

    foos.stream().forEach( System.out::println );

Dies wird ausdrucken:

Foo{bar='null'}
Foo{bar='aaa'}
Foo{bar='zzz'}

Es scheint mir, dass es keine Methode gibt, es zu tun, aber der Code ist trotzdem nicht so lang.

Sie sollten den NullComparator nicht so verwenden, wie Sie es tun - Sie erstellen eine neue Instanz der Klasse für jeden Vergleichsvorgang. Wenn Sie z. B. eine Liste mit 1000 Einträgen sortieren, sind dies 1000 * log2 (1000) Objekte sind völlig überflüssig. Dies kann schnell problematisch werden.

Entweder unterklagern Sie es oder delegieren Sie es oder implementieren Sie einfach Ihren eigenen Null -Check - es ist wirklich nicht so komplex:

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);
    }
}

Der Kunden als Pojo zu betrachten. Meine Antwort wäre:

Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId()));

Oder

Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo));

Ich denke

z.B

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.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top