Способ оптимизации компаратора - PullRequest
0 голосов
/ 06 августа 2020

Есть ли способ упорядочить имена людей по фамилии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;
           }
        });

1 Ответ

3 голосов
/ 06 августа 2020

Независимо от скорости ваш компаратор неверен.

Единственное, что следует считать равным, - это, ну, в общем, равные вещи. В настоящее время вы могли бы считать, что 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 < B и B < 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"))));

где nullsLast и comparing это методы из Comparator. (Вместо этого можно использовать nullsFirst, если вы предпочитаете обрабатывать значения NULL именно так).

С pre- Java 8 вы можете написать эквивалентное сравнение, используя вспомогательный метод:

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's ComparisonChain.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...