2017-03-15 3 views
1

Wie kann ich diese umschreiben:Java: Rewrite Vergleich Lambda - Nullsafe

private Comparator<Domain> byRank; 

... 

byRank = new Comparator<Domain>() { 
    @Override 
    public int compare(Domain d1, Domain d2) { 
    float tmp1 = d1.getDomainRank() == null ? 0 : d1.getDomainRank(); 
    float tmp2 = d2.getDomainRank() == null ? 0 : d2.getDomainRank(); 
    return Float.compare(tmp1, tmp2); 
    } 
}; 

in Lambda?

Nach check null value before sorting using lambda expression, habe ich versucht, diese:

byRank = Comparator.nullsFirst(Comparator.comparing(Domain::getDomainRank)); 

Es ist jedoch nicht mit:

java.lang.NullPointerException: null 
    at java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469) 
    at java.util.Comparators$NullComparator.compare(Comparators.java:83) 
    at java.util.PriorityQueue.siftUpUsingComparator(PriorityQueue.java:669) 
    at java.util.PriorityQueue.siftUp(PriorityQueue.java:645) 
    at java.util.PriorityQueue.offer(PriorityQueue.java:344) 
    at java.util.PriorityQueue.add(PriorityQueue.java:321) 

bearbeiten: das Lambda versagt, auch wenn ich für null vor dem Vergleich verglichenen Objekte überprüfen:

Queue<Domain> topByRank = new PriorityQueue<>(TOP, byRank); 

... 

for (Domain domain : domains) { 
    if (domain == null) { // check here 
    continue; 
    } 
    topByRank.add(domain); // here it fails 
} 
+0

Für was ich sehe d1 oder d2 sollte Null sein – freedev

+0

@freedev Ich überprüfe für Null-Objekt (siehe bearbeiten). Und die Nicht-Lambda-Version funktioniert ohne Fehler. Würde es nicht auch bei d1.getDomainRank() oder d2.getDomainRank() fehlschlagen? – Michal

+0

Comparator.comsparing wirft die NPE. Sie müssen die Anrufe umdrehen. Siehe http://stackoverflow.com/a/28500970/982149 – Fildor

Antwort

1

Ihr Code wird null Domain s zuerst setzen. Wenn Sie null Rang überprüfen möchten, müssen Sie dies verwenden:

Comparator.comparing(Domain::getDomainRank, Comparator.nullsFirst(Comparator.naturalOrder())) 

Aber bedenken Sie, dass dies zu Ihrem ursprünglichen Komparator nur entspricht, wenn der Rang nicht weniger als 0 anders sein kann, Sie werden einen ähnlichen Ausdruck testen:

Comparator.comparing(d -> d.getDomainRank() == null ? 0 : d.getDomainRank()) 

Alternativ könnten Sie gemeint Float.MIN_VALUE statt 0 in Ihrem ursprünglichen Code zu verwenden.

+0

Das ist es, und danke für diese Warnung über Nullgrenze. – Michal

1

Es shou ld sein:

Comparator.comparing(Domain::getDomainRank, 
      Comparator.nullsFirst(Comparator.naturalOrder())) 

Also sortieren wir eine Liste basierend auf domainRank. Aber was machen wir mit Domain Objekten, deren Wert domainRank Null ist? Wir werden sie an der Spitze unserer Sammlung halten: Comparator.nullsFirst(Comparator.naturalOrder())