优化比较器的方法

Way to optimize comparator

有没有比这更有效的方法来按姓氏 1 排序人名,如果不是,则按姓氏 2,如果不是,则按姓名? 这太慢了,谢谢!

        Collections.sort(lResult, new java.util.Comparator<Map>() {
           public int compare(Map m1, Map m2) {
               
               int lResult;            
               String i1= (String)m1.get("surname1");
               String i2= (String)m2.get("surname1");
               if((i1 == null) || (i2==null)) {lResult = 0;}
               else {lResult = i1.compareTo(i2);}
    
               if (lResult == 0) {                  
                    String t1= (String)m1.get("surname2");
                    String t2= (String)m2.get("surname2");
                    if((t1 == null) || (t2==null)) {lResult = 0;}
                    else {lResult = t1.compareTo(t2);}
                    
                }  
               
               if (lResult == 0) {
                    String x1= (String)m1.get("name");
                    String x2= (String)m2.get("name "); 
                    if((x1 == null) || (x2==null)) {lResult = 0;}
                    else {lResult = x1.compareTo(x2);}
                }  
                return lResult;
           }
        });

无论速度如何,您的比较器都不正确。

唯一应该被认为是平等的东西,呃,平等的东西。您当前会认为 null 等于 "non-null",因此这会导致奇怪的行为。

具体来说,您似乎在比较第一对对应的值,它们都是 non-null。这违反了 Comparator 实现的传递性要求。考虑一下,例如:

A = {"surname1": "A",  "surname2", null, "name": "A"}
B = {"surname1": null, "surname2", "B",  "name": "B"}
C = {"surname1": "A",  "surname2", "C",  "name": null}

根据您的比较器,A < BB < C。然而,A == C,因此使它成为一个无效的比较器。

正确地编写此比较器的最简单方法如下:

nullsLast(comparing(m -> (String) m.get("surname1")))
    .thenComparing(nullsLast(comparing(m -> (String) m.get("surname2"))))
    .thenComparing(nullsLast(comparing(m -> (String) m.get("name"))));

其中 nullsLastcomparing 是来自 Comparator 的方法。 (可以使用 nullsFirst 来代替,如果您更愿意这样处理空值的话)。

对于pre-Java8,你可以使用辅助方法写一个等价的比较:

public int compare(Map m1, Map m2) {
  int lResult;

  lResult = compare(m1, m2, "surname1");
  if (lResult != 0) return lResult;

  lResult = compare(m1, m2, "surname2");
  if (lResult != 0) return lResult;

  return compare(m1, m2, "name");
}

private int compare(Map m1, Map m2, String key) {
  String v1= (String)m1.get(key);
  String v2= (String)m2.get(key);
  if (v1 != null && v2 != null) {
    return v1.compareTo(v2);
  }
  return Boolean.compare(v1 != null, v2 != null);
}

或者使用类似 Guava 的 ComparisonChain