Way to optimize comparator

huangapple go评论57阅读模式
英文:

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;
    }
});
英文:

Is there any way to order people name's by surname1, if not, surname2, if not, name, more efficiently than this?
This is too slow, thanks!

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

答案1

得分: 3

不管速度如何,你的比较器都是不正确的。

唯一应该被视为相等的是相等的事物。你目前会认为 null 等于 &quot;non-null&quot;,所以这会导致奇怪的行为。

具体来说,你似乎正在比较第一对同时非空的对应值。这违反了比较器实现的传递性要求。例如,考虑以下情况:

A = {&quot;surname1&quot;: &quot;A&quot;,  &quot;surname2&quot;, null, &quot;name&quot;: &quot;A&quot;}
B = {&quot;surname1&quot;: null, &quot;surname2&quot;, &quot;B&quot;,  &quot;name&quot;: &quot;B&quot;}
C = {&quot;surname1&quot;: &quot;A&quot;,  &quot;surname2&quot;, &quot;C&quot;,  &quot;name&quot;: null}

根据你的比较器,A &lt; BB &lt; C。但是,A == C,这使它成为一个无效的比较器。

编写这个比较器的最简单方法 - 正确的方法 - 可能是这样的:

nullsLast(comparing(m -&gt; (String) m.get(&quot;surname1&quot;)))
    .thenComparing(nullsLast(comparing(m -&gt; (String) m.get(&quot;surname2&quot;))))
    .thenComparing(nullsLast(comparing(m -&gt; (String) m.get(&quot;name&quot;))));

其中 nullsLastcomparingComparator 中的方法。(如果你更喜欢处理 nulls 的话,可以使用 nullsFirst 代替)。

在 Java 8 之前,你可以使用一个辅助方法编写等效的比较:

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

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

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

  return compare(m1, m2, &quot;name&quot;);
}

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

或者使用类似 Guava 的 ComparisonChain

英文:

Irrespective of speed, your comparator isn't correct.

The only things which should be considered equal are, well, equal things. You would currently consider null to be equal to &quot;non-null&quot;, and so that would lead to odd behavior.

Specifically, what you seem to be doing is comparing the first pair of corresponding values which are both non-null. This violates the transitivity requirement of Comparator implementations. Consider, for example:

A = {&quot;surname1&quot;: &quot;A&quot;,  &quot;surname2&quot;, null, &quot;name&quot;: &quot;A&quot;}
B = {&quot;surname1&quot;: null, &quot;surname2&quot;, &quot;B&quot;,  &quot;name&quot;: &quot;B&quot;}
C = {&quot;surname1&quot;: &quot;A&quot;,  &quot;surname2&quot;, &quot;C&quot;,  &quot;name&quot;: null}

According to your comparator, A &lt; B and B &lt; C. However, A == C, thus making it an invalid comparator.

The easiest way to write this Comparator - correctly - would be something like:

nullsLast(comparing(m -&gt; (String) m.get(&quot;surname1&quot;)))
    .thenComparing(nullsLast(comparing(m -&gt; (String) m.get(&quot;surname2&quot;))))
    .thenComparing(nullsLast(comparing(m -&gt; (String) m.get(&quot;name&quot;))));

where nullsLast and comparing are methods from Comparator. (nullsFirst can be used instead, if that's how you'd prefer to handle nulls).

With pre-Java 8, you can write an equivalent comparison using a helper method:

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

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

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

  return compare(m1, m2, &quot;name&quot;);
}

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

Or use something like Guava's ComparisonChain.

huangapple
  • 本文由 发表于 2020年8月6日 17:08:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/63280327.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定