英文:
CompareTo method in two separate methods
问题
我有一个实现了Comparable接口的类。
我想按照对象的ID和名称进行排序,但是分别在两个不同的方法中。
例如,按ID排序:
public int compareTo(Metro m1) {
return this.id - m1.id;
}
我还想按名称排序,这意味着我必须这样做:
public int compareTo(Metro m1) {
return this.name.compareTo(m1.name);
}
问题是我不能用相同的名称和参数编写相同的函数,我该怎么做来解决这个问题?
当我在对象列表上调用Collections.sort(this.list);
时,它如何确定我想按ID还是按名称对列表进行排序?
英文:
I have a class that implements the Comparable interface.
I want to sort objects by their id and by their name, but in two seperate methods.
For example, sorting by id:
public int compareTo(Metro m1) {
return this.id - m1.id;
}
I also want to sort by name, which means that I have to do something like this:
public int compareTo(Metro m1) {
return this.name.compareTo(m1.name);
}
The problem is that I can't write the same function with the same name and the same parameters, how do I do to fix this?
When I will call Collections.sort(this.list);
on a list of objects, how is it going to identify that I want to sort my list by id or by name?
答案1
得分: 5
实现 Comparable
接口适用于具有所谓的“自然顺序”的类型。这将是一种毋庸置疑的顺序,对于“没有任何进一步的上下文,你认为这些对象如何排序?”这个问题,会有一个明显的答案。
例如,如果我让你排序 '1, 9 和 7',没有进一步的上下文,你肯定会想:嗯,我猜是 1, 7, 9?然后如果我告诉你:实际上我希望你用英文拼出这些数字,然后按照拼写的长度排序,那么结果就是 1, 9, 7 - 这显然是出乎意料的。
在你的情况下,'按名称排序' 和 '按标识排序' 听起来同样合理。
这意味着 Metro
类型根本没有任何自然顺序,因此不应该实现 Comparable 接口。
那么,如何进行排序呢?幸运的是,sort()
方法有一个重载:你可以提供一个 Comparator 对象。这就是解决这个问题的方法:
// 假设 getId() 是一个存在的方法:
Comparator<Metro> byUnid = comparingInt(Metro::getId);
this.list.sort(byUnid);
// 这可以工作,因为字符串具有自然顺序
Comparator<Metro> byName = comparing(Metro::getName)
就是这么简单。请注意,你的按标识比较的方法有问题 - 它在处理非常大的数值时会失败。你应该尽量使用 comparing
、comparingInt
以及 Comparator 接口中的链式解决方案。
英文:
implementing Comparable
is appropriate if an type has a so-called 'natural order'. That'd be an order that is the slam dunk answer to 'without any further context, how do you think these objects would be ordered'?
For example, if I ask you to order '1, 9, and 7', without further context, surely you'd go: Well, uh, I guess 1,7,9? If then later I tell you: Actually I wanted you to spell those digits out in english and then sort on the length of that, so, 1,9,7 - okay, but that's quite unexpected.
In your case, both 'by name' and 'by id' sound equally plausible.
This means that a Metro
type has no natural order at all, and therefore should not implement Comparable.
So, how do you sort em? Fortunately, sort()
has an overload: You can supply a Comparator object. That's how you solve this problem:
// requires getId() to exist as a method:
Comparator<Metro> byUnid = comparingInt(Metro::getId);
this.list.sort(byUnid);
// Works because strings do have natural order
Comparator<Metro> byName = comparing(Metro::getName)
It's that simple. Note that your compareTo by id method is broken - it fails for very large numbers. You should endeavour to use the comparing
, comparingInt
, and chaining solutions in the Comparator interface.
答案2
得分: 0
你可以使用 java.util.Comparator
:
Comparator<MyClass> comparatorByName = Comparator.comparing(a -> a.name);
Comparator<MyClass> comparatorById = Comparator.comparing(a -> a.id);
List<MyClass> list = new ArrayList<>();
// ...
Collections.sort(list, comparatorByName);
Collections.sort(list, comparatorById);
英文:
You can use java.util.Comparator
:
Comparator<MyClass> comparatorByName = Comparator.comparing(a -> a.name);
Comparator<MyClass> comparatorById = Comparator.comparing(a -> a.id);
List<MyClass> list = new ArrayList<>();
// ...
Collections.sort(list, comparatorByName);
Collections.sort(list, comparatorById);
答案3
得分: 0
只要您的Comparable对象不在排序集合中(TreeSet等),您只需为单个排序提供一个实例Comparator。
按Y坐标排序
List<Point2D> points = new ArrayList();
Collections.sort(points, new Comparator<>() {
@Override
public int compare(Point2D o1, Point2D o2) {
return Double.compare(o1.getY(), o2.getY());
}
});
按X坐标排序
Collections.sort(points, new Comparator<>() {
@Override
public int compare(Point2D o1, Point2D o2) {
return Double.compare(o1.getX(), o2.getX());
}
});
英文:
So long as you don't have your Comparable object in a sorted collection (TreeSet, etc)
you can just provide an instance Comparator for a single sort.
Sorting by Y coord
List<Point2D> points = new ArrayList();
Collections.sort(points, new Comparator<>() {
@Override
public int compare(Point2D o1, Point2D o2) {
return Double.compare(o1.getY(), o2.getY());
}
});
Sorting by X coord
Collections.sort(points, new Comparator<>() {
@Override
public int compare(Point2D o1, Point2D o2) {
return Double.compare(o1.getX(), o2.getX());
}
});
答案4
得分: 0
import java.util.ArrayList;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
ArrayList<Metro> l = new ArrayList<>();
l.add(new Metro(5, "aziz"));
l.add(new Metro(1, "zied"));
l.add(new Metro(2, "ahmed"));
Comparator<Metro> byId = new Comparator<Metro>() {
@Override
public int compare(Metro o1, Metro o2) {
return o1.getId() - o2.getId();
}
};
l.sort(byId);
System.out.println("by id :" + l);
Comparator<Metro> byName = new Comparator<Metro>() {
@Override
public int compare(Metro o1, Metro o2) {
return o1.getName().compareTo(o2.getName());
}
};
l.sort(byName);
System.out.println("by name :" + l);
}
}
class Metro {
private String name;
private int id;
Metro(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "{" + id + "," + name + "}";
}
}
输出:
by id :[{1,zied}, {2,ahmed}, {5,aziz}]
by name :[{2,ahmed}, {5,aziz}, {1,zied}]
英文:
import java.util.ArrayList;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
ArrayList<Metro> l = new ArrayList<>();
l.add(new Metro(5, "aziz"));
l.add(new Metro(1, "zied"));
l.add(new Metro(2, "ahmed"));
Comparator<Metro> byId = new Comparator<Metro>() {
@Override
public int compare(Metro o1, Metro o2) {
return o1.getId() - o2.getId();
}
};
l.sort(byId);
System.out.println("by id :" + l);
Comparator<Metro> byName = new Comparator<Metro>() {
@Override
public int compare(Metro o1, Metro o2) {
return o1.getName().compareTo(o2.getName());
}
};
l.sort(byName);
System.out.println("by name :" + l);
}
}
class Metro {
private String name;
private int id;
Metro(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
@Override
public String toString() {
return "{" + id + "," + name + "}";
}
}
output :
by id :[{1,zied}, {2,ahmed}, {5,aziz}]
by name :[{2,ahmed}, {5,aziz}, {1,zied}]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论