您有两种基本方法:
-
给
Edge一个自然排序。然后所有的排序函数都将默认使用它——就像其他任何可以使用排序的函数一样(例如 SortedMap 和 binarySearch() 方法中的键顺序)。
您可以通过实现Comparable 接口来做到这一点。这只有一个方法,compareTo(),它可以很简单:
public class Edge(val v: Int, val u: Int, val weight: Double) : Comparable<Edge> {
override fun compareTo(other: Edge) = weight.compareTo(other.weight)
}
但是,这并没有为具有相同权重的实例提供一致的顺序,因此您可能还希望使用其他属性作为决胜局,例如:
override fun compareTo(other: Edge)
= weight.compareTo(other.weight).takeIf{ it != 0 }
?: v.compareTo(other.v).takeIf{ it != 0 }
?: u.compareTo(other.u)
(实现这一点有一些微妙之处,特别是如果您没有同时覆盖 equals() 以直接对应。 Java documentation 值得一读。)
请注意,data class 按其构造函数中的属性自动实现Comparable。所以你通常不需要担心订购。
-
排序时提供排序。
其他答案对此进行了讨论。也许最简单的方法是:
sides.sortBy{ it.weight }
虽然有很多选择,比如:
sides.sortWith{ a, b -> a.weight.compareTo(b.weight) }
或者您可以创建一个Comparator 实例,以便在必要时重复使用:
val comparator = Comparator<Edge>{ o1, o2 -> o1.weight.compareTo(o2.weight) }
sides.sortWith(comparator)
同样,比较器可以与标准库中的许多函数一起使用,因此您可以避免重复权重比较代码。
选择哪种方法取决于您的需求。
如果您的边缘始终按重量排列是直观的,那么自然排序将是一个很好的选择。这对代码来说很简洁:您只需在一个地方实现Comparable(或者将您的类设为data class,并首先指定权重属性),然后您就可以享受到处订购的全部好处。 (当然,只有在您可以控制 Edge 源代码的情况下才能这样做。)
另一方面,如果基于权重的排序特定于特定方法(如果您可能希望在其他地方有不同的排序),那么在排序时指定排序会更有意义。
当然,如果需要,您可以同时进行这两种操作:您可以为对象提供适用于大多数事情的自然顺序,然后为特定操作指定不同的顺序。