比较器,排序集合 - 1

“嗨,阿米戈!”

“嗨,比拉博!”

“今天我们将研究一个小而有趣且有用的主题:对集合进行排序。”

“分院?我听说过。”

“很久以前,每个程序员都必须能够编写排序算法。能够并且必须编写它们。但那些日子已经过去了。今天,编写自己的排序代码被认为是一种糟糕的形式,就像重写任何已经存在的东西一样被发明了。”

“在 Java(和其他编程语言)中,已经实现了排序。 你的任务是学习如何正确使用已经存在的东西。

“好的。”

Collections helper 类有一个静态排序方法,用于对集合进行排序——或者更准确地说,列表。Maps 和 Sets 中的元素没有顺序/索引,所以没有什么可排序的。”

“是的,我记得。我曾经用这种方法对数字列表进行排序。”

“太棒了。但是这个方法比乍看起来要强大得多。它不仅可以对数字进行排序,还可以根据任何标准对任何对象进行排序。有两个接口可以帮助该方法做到这一点: Comparable 和 Comparator

“有时你需要对对象而不是数字进行排序。例如,假设你有一个人的列表,你想按年龄对他们进行排序。我们为此提供了 Comparable 接口。

“让我先给你举个例子,然后一切都会变得更清楚:”

例子
public class Woman implements Comparable<Woman>
{
public int age;

public Woman(int age) {
this.age = age;
}

public int compareTo(Woman o)
{
return this.age - o.age;
}
}
如何使用它的示例:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Collections.sort(women);
}

“要对对象进行排序,您必须首先知道如何比较它们。为此,我们使用 Comparable。Comparable接口是泛型的,这意味着它接受类型参数。它只有一个泛型方法:compareTo(To)。这个方法比较当前对象(this)和作为参数传递的对象(o)。换句话说,我们需要在我们的类中实现这个方法,然后用它来比较当前对象(this)和传递的对象。 “

“compareTo 是如何工作的?我预计它会返回 true 或 false,这取决于传递的对象是更大还是更小。”

“这里的事情比较棘手。compareTo 方法不返回 true/false。相反,它返回一个 int。这样做实际上是为了简单起见。

“当计算机需要确定一个数是否大于另一个数时,它只需从第一个数中减去第二个数,然后查看结果。如果结果为 0,则两个数相等。如果结果小于零,则第二个数更大。如果结果大于零,则第一个数更大。”

“同样的逻辑也适用于此。根据规范,如果比较的对象相等,compareTo 方法必须返回零。如果 compareTo 方法返回大于零的数字,那么我们的对象大于传递的对象。“如果 compareTo方法返回一个小于零的数字,那么'this'小于传递的对象。”

“这有点奇怪。”

“是的,但如果你只是简单地根据一些数字属性来比较对象,那么你可以通过一个减去另一个来返回它们之间的差异。就像上面例子中所做的那样。”

public int compareTo(Woman o)
{
return this.age - o.age;
}

“我想我什么都懂。但也许不是。但几乎是所有。”

“太好了。现在让我们考虑一个更实际的问题。假设你写了一个很酷的网站,用于在中国制作女装。你使用 Woman 类来描述你的客户。你甚至制作了一个带有表格的网页,你可以在其中看到所有这些.但是有一个问题……”

“您的 Woman 对象不仅包含年龄,还包含一大堆其他数据:名字、姓氏、身高、体重、孩子数量等。”

“用户表有很多列,问题来了:如何根据各种标准对用户进行排序?按体重、年龄、姓氏?”

“嗯。是的,我经常看到可以让你按列排序的表格。那么,你是怎么做到的?”

“为此,我们有我今天想告诉你的第二个接口:Comparator 接口。它也有一个比较方法,但它需要两个参数,而不是一个:int compare(T o1, T o2)。这是它的方式作品:”

例子
public class Woman
{
public int age;
public int childrenCount;
public int weight;
public int height;
public String name;

public Woman(int age) {
this.age = age;
}
}
如何使用它的示例:
public static void main(String[] args )
{
ArrayList<Woman> women = new ArrayList<Woman>();
women.add(new Woman(18));
women.add(new Woman(21));
women.add(new Woman(5));

Comparator<Woman> compareByHeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.height - o2.height;
}
};

Collections.sort(women, compareByHeight);
}

“Comparator 接口不会将对象比较逻辑隐藏在被比较对象的类中。相反,它是在一个单独的类中实现的。”

“所以,我可以创建几个实现 Comparator 接口的类,让每个类比较不同的属性?一个是体重,另一个是年龄,第三个是身高?”

“是的,非常简单方便。”

“我们只是调用Collections.sort方法,将对象列表和另一个特殊对象作为第二个参数传递,它实现了Comparator接口并告诉您如何在排序过程中正确比较对象对。”

“嗯,我想我都明白了,我试试看,假设我需要按权重对用户进行排序,大概是这样的:”

按权重排序用户示例:
Comparator<Woman> compareByWeight = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.weight - o2.weight;
}
};

Collections.sort(women, compareByWeight);

“对,就是这样。”

“太好了。但是如果我想倒序排序怎么办?”

“想想看,答案很简单!”

“我明白了!就像这样:”

按升序排序:
return o1.weight - o2.weight;
降序排列:
return o2.weight – o1.weight;

“对。干得好。”

“如果我想按姓氏排序?我该如何对字符串排序,Bilaabo?”

“String 类已经实现了 compareTo 方法。您只需调用它:”

按名称对用户进行排序的示例:
Comparator<Woman> compareByName = new Comparator<Woman>() {
public int compare(Woman o1, Woman o2) {
return o1.name.compareTo(o2.name);
}
};

Collections.sort(women, compareByName);

“这是一个很好的教训,Bilaabo。非常感谢你。”

“谢谢你,我的朋友!”