在两个单独的方法中比较 CompareTo 方法。

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

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)

就是这么简单。请注意,你的按标识比较的方法有问题 - 它在处理非常大的数值时会失败。你应该尽量使用 comparingcomparingInt 以及 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&lt;Metro&gt; byUnid = comparingInt(Metro::getId);
this.list.sort(byUnid);

// Works because strings do have natural order
Comparator&lt;Metro&gt; 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&lt;MyClass&gt; comparatorByName = Comparator.comparing(a -&gt; a.name);
Comparator&lt;MyClass&gt; comparatorById = Comparator.comparing(a -&gt; a.id);
List&lt;MyClass&gt; list = new ArrayList&lt;&gt;();
// ...
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&lt;Point2D&gt; points = new ArrayList();        
Collections.sort(points, new Comparator&lt;&gt;() {
        @Override
        public int compare(Point2D o1, Point2D o2) {
            return Double.compare(o1.getY(), o2.getY());
        }
 });

Sorting by X coord

 Collections.sort(points, new Comparator&lt;&gt;() {
            @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&lt;Metro&gt; l = new ArrayList&lt;&gt;();
l.add(new Metro(5, &quot;aziz&quot;));
l.add(new Metro(1, &quot;zied&quot;));
l.add(new Metro(2, &quot;ahmed&quot;));
Comparator&lt;Metro&gt; byId = new Comparator&lt;Metro&gt;() {
@Override
public int compare(Metro o1, Metro o2) {
return o1.getId() - o2.getId();
}
};
l.sort(byId);
System.out.println(&quot;by id :&quot; + l);
Comparator&lt;Metro&gt; byName = new Comparator&lt;Metro&gt;() {
@Override
public int compare(Metro o1, Metro o2) {
return o1.getName().compareTo(o2.getName());
}
};
l.sort(byName);
System.out.println(&quot;by name :&quot; + 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 &quot;{&quot; + id + &quot;,&quot; + name + &quot;}&quot;;
}
}

output :

by id :[{1,zied}, {2,ahmed}, {5,aziz}]
by name :[{2,ahmed}, {5,aziz}, {1,zied}]

huangapple
  • 本文由 发表于 2020年10月19日 07:14:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/64419237.html
匿名

发表评论

匿名网友

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

确定