2010-04-30 66 views
1

我只想使用Collections.sort或Arrays.sort按x先排序列表(class Point),然后按y排序。如何排序数组或ArrayList <Point> ASC首先由x再由y?

我有一个先斗类实现可比这样的:

public int compareTo(Ponto obj) { 
     Ponto tmp = obj; 
     if (this.x < tmp.x) { 
      return -1; 
     } else if (this.x > tmp.x) { 
      return 1; 
     } 
     return 0; 
    } 

但现在我想通过Y X后也进行排序。

我该怎么做,通过修改上面的代码?或者,这是一个更好和“干净”的方式来做到这一点? 我也用这个代码传递给C++,其中我创建了一个名为Point的结构,并带有一个等效的可比较方法。

+0

什么是'this.x'的类型,是int,float,double ...? – fredoverflow 2010-04-30 13:59:32

+0

x和y是整数。我只创建了Ponto类来实现Comparable <>接口,并且使用x,y整数而不是double。我已经看到了下面的建议。也感谢你的贡献。 – neverMind 2010-04-30 15:48:28

回答

6

this.yobj.y的相同比较算法取代return 0

顺便说一句,重新分配到tmp在这里是不必要的。优化的图片可以看起来像:

public int compareTo(Ponto other) { 
    if (this.x == other.x) { 
     return (this.y < other.y) ? -1 : ((this.y == other.y) ? 0 : 1); 
    } else { 
     return (this.x < other.x) ? -1 : 1; 
    } 
} 
+1

当然,你不应该使用这种减法技术,除非你能保证它不会溢出(参见http://stackoverflow.com/questions/2728793/java-integer-what-is-faster-comparison-or-subtraction /) – polygenelubricants 2010-04-30 01:54:34

+1

@ poly:非常真实,有点傻,我更新了答案。 – BalusC 2010-04-30 01:59:37

2

BalusC提供正确的答案:基本上你在yx为主。这是一个使用嵌套三元运算符编写的变体,它使优先级清晰。

public int compareTo(Ponto other) { 
    return 
     (this.x < other.x) ? -1 : 
     (this.x > other.x) ? +1 : 
     (this.y < other.y) ? -1 : 
     (this.y > other.y) ? +1 : 
     0; 
} 

另一种方式来做到这一点,如果你不想编写自定义Comparator<T>为每个优先级方案,是使用稳定算法进行多重排序。

如果您想通过x(初级)命令,然后y(次),则:

  • 排序上y第一(!!!)
  • 然后排序上x使用一个稳定的排序

这仍然是渐近O(N log N)但当然你正在做多个阶段。当你有很多排序标准时,这很方便。而不是编写复杂的代码,只做多个阶段(并且只有在证明必要时才进行优化)。

因此,如果您对键排序​​,k2k3,...,kM,按照优先顺序,你这样做:

  • 排序上kM
  • 稳定的排序上kM-1
  • ...
  • 稳定排序​​
  • 完成!

请注意,Collections.sort是稳定的。

这类保证是稳定:相等的元素将不被重新排序作为排序的结果。

+1

这一个确实是更好的可读性:) – BalusC 2010-04-30 02:19:06

+1

@BalusC:只有你对嵌套三元组感到满意。我一直在尖叫使用它。 – polygenelubricants 2010-04-30 02:20:23

+1

你已经习惯了它多年。这对老年人来说就像是美味的酒,而对于年轻人而言则是无味的啤酒。 – BalusC 2010-04-30 02:22:46