将collections.sort()与compareTo一起使用,而不是排序

时间:2017-11-08 16:28:36

标签: java class

所以目前我正在进行一项任务,我必须有两个班级,一个名为Fysiker,另一个名为人类。 Fysiker只是Human类的扩展。人类有两个属性:姓名和年龄,而Fysiker有三个:姓名,年龄和年初。我已经创建了一个同时包含Human和Fysiker的数组,我想先按年龄排序,但如果两个fysiker具有相同的年龄,我希望它按我的第三个属性排序:startyear。

我对compareTo的理解(我需要使用compareTo,为了练习)是有限的,但从我所读到的它是一个可比较的自动与Collections.sort()交互,我的代码目前看起来像这样:

import java.util.List;
import java.util.Arrays;
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;
public class Fysiker extends Human{

    public int startyear;
    public Fysiker(int age, String name, int startyear){
        this.age=age;
        this.name=name;
        this.startyear=startyear;
    }

    public int getYear(){
        return startyear;
    }
    public int compareTo(Fysiker o){
        int b;
        b=(this.age>o.age ? 1:this.age<o.age ? -1:0);
        if (b==0){
            b=(this.startyear>o.startyear ? 1:this.startyear<o.startyear ? -1:0);
            return b;}
            else{
            return b;}

    }
    public String toString(){
        return "åldern är:"+this.age+" "+"namnet är:"+this.name+" "+"började fysik:"+String.format("F%02d",this.startyear%100);
    }

    public Fysiker(){
        this.age=15+rand.nextInt(86);
        this.name=names.get(rand.nextInt(names.size()));
        this.startyear=2015-rand.nextInt(this.age-14);
        while (this.startyear<1932){
            this.startyear=2015-rand.nextInt(this.age-14);
    }
}
    public static void main(String[] args){
        ArrayList<Human> fysiker=new ArrayList<Human>();
        int q;


        for (q=0;q<=80;q++){
            fysiker.add(new Fysiker());
            //fysiker.add(new Human());

            //System.out.println(fysiker.get(q).toString());
        }
        int s;
        Collections.sort(fysiker);
        for (s=0;s<=fysiker.size()-1;s++){
            //fysiker.get(0).compareTo(fysiker.get(s));
            System.out.println(fysiker.get(s).toString());
            //System.out.println(fysiker.get(0));
        }
    }

}

人类反过来:

import java.util.List;
import java.util.Arrays;
import java.util.Random;
import java.util.ArrayList;
public class Human implements Comparable<Human>{
        public static final List<String> names = Arrays.asList("Rutger","Oscar","Aram","Noak","Hilda","Dahl");
        public Random rand=new Random();
        public String name;
        public int age;

    public Human(int age, String name){
        this.age=age;
        this.name=name;

    }
    public Human(){
        this.age=rand.nextInt(101);
        this.name=names.get(rand.nextInt(names.size()));
    }

    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
    public String toString(){
        return "åldern är:"+this.age+" "+"namnet är:"+this.name;
    }
    public int compareTo(Human o){
        return this.age-o.age;
}
}

我的问题是它在初学年之后没有排序,但我可以修复它,如果我从我的Human类中删除compareTo,但我也需要那个,我想要对它们进行排序,但它修复了“不是在startyear之后为fysiker“-problem排序。我从哪里开始?

2 个答案:

答案 0 :(得分:2)

实际上是子类中定义的方法:

public int compareTo(Fysiker o){

不会覆盖基类中的方法:

public int compareTo(Human o){

您可以使用相同的签名定义子类以有效覆盖:

public int compareTo(Human o){

并使用instanceof根据实际类型进行比较 但这也不是一个好主意。 实际上,Fysiker会知道如何比较HumanFysiker,但Human会知道如何只比较Human s。

Comparable.compareTo()合同规定:

  

实现者还必须确保关系是可传递的:   ((compare(x,y)&gt; 0)&amp;&amp;(compare(y,z)&gt; 0))暗示比较(x,z)> 0。

Comparable不应该尝试在类之间互操作,因为它可能违反传递性比较原则。

我认为在您的情况下,作为替代方案,您应该使用Comparator对元素进行排序。

你有两种方式。

1)如果列表仅包含Fysiker个实例,请声明List Fysiker并创建Comparator<Fysiker>

List<Fysiker> fysiker = new ArrayList<Fysiker>();
...
Collections.sort(fysiker);

它限制了List可以接受的元素的类型,但在这种特定情况下是希望的。

2)如果列表同时包含HumanFysiker个实例,请声明List Human并创建Comparator<Human>

List<Human> humans = new ArrayList<Human>();
...
Collections.sort(fysiker);

Comparator实现中,您应该检查实例的类型并根据以下内容进行比较:

public class ComparatorHumanAndFysiker implements Comparator<Human>{

      public int compare(Human o1, Human o2){

           if (o1 instanceof Fysiker && o2 instanceof Fysiker){
              Fysiker f1 = (Fysiker) o1;
              Fysiker f2 = (Fysiker) o2;
              // specific comparison
              return ...;
           }

            // else mixed type comparison or human comparison              
            return o1.age - o2.age;                         
        }
 } 

答案 1 :(得分:0)

在排序期间,仅使用compareTo(Human o)方法。由于您未实现compareTo(Fysiker o)接口,因此永远不会使用Comparable<Fysiker>。遗憾的是,对于具体的类继承,您的Fysiker类将无法实现Comparable<Fysiker>,因为它已经间接实现了Comparable<Human>接口,而在Java中,您无法使用不同的泛型类型实现相同的接口。

作为一种快速解决方法,您可以覆盖compareTo(Human o)类中的Fysiker,而不是定义重载的compareTo(Fysiker o)方法:

public int compareTo(Human o){
    int b;
    b=(this.age>o.age ? 1:this.age<o.age ? -1:0);

    if (b==0 && o instanceof Fysiker){
        b= ( this.startyear> ( (Fysiker) o ).startyear ? 1:this.startyear< ( (Fysiker)o ).startyear ? -1:0);
        return b;
    }else{
        return b;
    }

}

<强>更新

我认为这种方法更清洁:

public int compareTo(Human o){
        int age1 = this.age;
        int age2 = o.age;

        int result = age1 - age2;
        if (result != 0) return result;

        int startyear1 = this.startyear;
        int startyear2 = (o instanceof Fysiker) ? ( (Fysiker)o ).startyear : 0;

        return startyear1 - startyear2;
    }

<强>输出:

åldern är:0 namnet är:Oscar
åldern är:5 namnet är:Oscar
åldern är:6 namnet är:Aram
åldern är:6 namnet är:Dahl
åldern är:7 namnet är:Aram
åldern är:8 namnet är:Oscar
åldern är:10 namnet är:Oscar
åldern är:12 namnet är:Noak
åldern är:14 namnet är:Aram
åldern är:15 namnet är:Aram
åldern är:15 namnet är:Oscar
åldern är:16 namnet är:Aram
åldern är:17 namnet är:Dahl
åldern är:17 namnet är:Hilda
åldern är:18 namnet är:Noak
åldern är:18 namnet är:Noak började fysik:F2015
åldern är:18 namnet är:Oscar
åldern är:18 namnet är:Oscar började fysik:F2014
åldern är:19 namnet är:Noak
åldern är:19 namnet är:Oscar började fysik:F2013
åldern är:19 namnet är:Hilda började fysik:F2015
åldern är:19 namnet är:Noak
åldern är:20 namnet är:Hilda började fysik:F2011
åldern är:20 namnet är:Dahl
åldern är:21 namnet är:Hilda började fysik:F2015
åldern är:21 namnet är:Rutger
åldern är:21 namnet är:Dahl
åldern är:21 namnet är:Dahl började fysik:F2009
åldern är:21 namnet är:Noak började fysik:F2009
åldern är:21 namnet är:Aram började fysik:F2015
åldern är:22 namnet är:Rutger började fysik:F2011
åldern är:22 namnet är:Hilda
åldern är:22 namnet är:Aram
åldern är:22 namnet är:Oscar
åldern är:24 namnet är:Rutger började fysik:F2006
åldern är:24 namnet är:Hilda
åldern är:24 namnet är:Oscar
åldern är:26 namnet är:Hilda började fysik:F2013
åldern är:27 namnet är:Noak började fysik:F2012
åldern är:27 namnet är:Hilda började fysik:F2013
åldern är:28 namnet är:Rutger
åldern är:28 namnet är:Dahl
åldern är:28 namnet är:Oscar började fysik:F2004
åldern är:29 namnet är:Aram började fysik:F2007
åldern är:29 namnet är:Aram började fysik:F2013
åldern är:29 namnet är:Rutger började fysik:F2013
åldern är:31 namnet är:Oscar började fysik:F2009
åldern är:31 namnet är:Dahl
åldern är:31 namnet är:Oscar
åldern är:33 namnet är:Aram började fysik:F2004
åldern är:33 namnet är:Aram började fysik:F2008
åldern är:34 namnet är:Noak
åldern är:34 namnet är:Noak började fysik:F2007
åldern är:34 namnet är:Hilda
åldern är:34 namnet är:Hilda började fysik:F1999
åldern är:35 namnet är:Aram
åldern är:35 namnet är:Hilda började fysik:F2010
åldern är:36 namnet är:Noak
åldern är:36 namnet är:Oscar
åldern är:38 namnet är:Hilda började fysik:F1999
åldern är:39 namnet är:Rutger började fysik:F2013
åldern är:42 namnet är:Dahl
åldern är:43 namnet är:Oscar
åldern är:43 namnet är:Noak började fysik:F2002
åldern är:43 namnet är:Aram
åldern är:43 namnet är:Oscar
åldern är:44 namnet är:Rutger
åldern är:44 namnet är:Aram
åldern är:44 namnet är:Oscar
åldern är:44 namnet är:Dahl
åldern är:45 namnet är:Oscar
åldern är:47 namnet är:Oscar började fysik:F1986
åldern är:48 namnet är:Hilda
åldern är:50 namnet är:Dahl började fysik:F2004
åldern är:50 namnet är:Dahl började fysik:F2008
åldern är:50 namnet är:Rutger
åldern är:51 namnet är:Hilda började fysik:F2014
åldern är:52 namnet är:Aram
åldern är:54 namnet är:Noak
åldern är:56 namnet är:Noak började fysik:F2011
åldern är:56 namnet är:Aram
åldern är:56 namnet är:Dahl
åldern är:56 namnet är:Rutger började fysik:F2009
åldern är:58 namnet är:Aram
åldern är:59 namnet är:Oscar började fysik:F1982
åldern är:59 namnet är:Oscar
åldern är:60 namnet är:Aram började fysik:F1985
åldern är:60 namnet är:Hilda
åldern är:60 namnet är:Aram
åldern är:61 namnet är:Aram började fysik:F1976
åldern är:61 namnet är:Hilda började fysik:F2003
åldern är:62 namnet är:Hilda
åldern är:63 namnet är:Noak började fysik:F1989
åldern är:63 namnet är:Dahl
åldern är:63 namnet är:Oscar
åldern är:64 namnet är:Hilda började fysik:F2013
åldern är:65 namnet är:Hilda började fysik:F1998
åldern är:65 namnet är:Dahl började fysik:F1998
åldern är:67 namnet är:Rutger började fysik:F1968
åldern är:67 namnet är:Rutger började fysik:F1972
åldern är:68 namnet är:Hilda
åldern är:69 namnet är:Noak började fysik:F2007
åldern är:69 namnet är:Hilda
åldern är:69 namnet är:Noak
åldern är:70 namnet är:Rutger började fysik:F1977
åldern är:70 namnet är:Noak började fysik:F2000
åldern är:71 namnet är:Dahl började fysik:F1961
åldern är:71 namnet är:Aram började fysik:F2009
åldern är:72 namnet är:Oscar
åldern är:73 namnet är:Dahl började fysik:F1998
åldern är:75 namnet är:Noak
åldern är:75 namnet är:Hilda
åldern är:76 namnet är:Hilda
åldern är:76 namnet är:Noak började fysik:F1998
åldern är:76 namnet är:Dahl
åldern är:77 namnet är:Oscar
åldern är:77 namnet är:Aram
åldern är:78 namnet är:Rutger började fysik:F1958
åldern är:78 namnet är:Oscar
åldern är:79 namnet är:Rutger började fysik:F1958
åldern är:79 namnet är:Aram började fysik:F1960
åldern är:79 namnet är:Aram började fysik:F1967
åldern är:79 namnet är:Hilda
åldern är:80 namnet är:Oscar började fysik:F1961
åldern är:80 namnet är:Oscar började fysik:F1969
åldern är:80 namnet är:Oscar började fysik:F2007
åldern är:81 namnet är:Rutger började fysik:F1996
åldern är:81 namnet är:Oscar
åldern är:81 namnet är:Aram började fysik:F2011
åldern är:85 namnet är:Dahl
åldern är:87 namnet är:Hilda
åldern är:88 namnet är:Dahl började fysik:F1976
åldern är:88 namnet är:Rutger
åldern är:88 namnet är:Hilda började fysik:F1968
åldern är:88 namnet är:Hilda började fysik:F2003
åldern är:88 namnet är:Oscar började fysik:F2005
åldern är:88 namnet är:Oscar började fysik:F2005
åldern är:89 namnet är:Noak började fysik:F1970
åldern är:89 namnet är:Noak
åldern är:89 namnet är:Dahl
åldern är:90 namnet är:Noak började fysik:F1975
åldern är:91 namnet är:Oscar började fysik:F1984
åldern är:91 namnet är:Hilda
åldern är:91 namnet är:Dahl
åldern är:91 namnet är:Aram
åldern är:92 namnet är:Rutger
åldern är:92 namnet är:Aram började fysik:F1997
åldern är:94 namnet är:Oscar började fysik:F1936
åldern är:95 namnet är:Dahl
åldern är:95 namnet är:Rutger började fysik:F1940
åldern är:96 namnet är:Hilda började fysik:F1945
åldern är:96 namnet är:Rutger började fysik:F1962
åldern är:96 namnet är:Aram började fysik:F1994
åldern är:96 namnet är:Noak började fysik:F1997
åldern är:97 namnet är:Dahl började fysik:F1941
åldern är:97 namnet är:Oscar började fysik:F1958
åldern är:97 namnet är:Oscar började fysik:F2014
åldern är:98 namnet är:Oscar började fysik:F1973
åldern är:98 namnet är:Hilda började fysik:F2012
åldern är:99 namnet är:Noak började fysik:F1951
åldern är:100 namnet är:Noak
åldern är:100 namnet är:Dahl började fysik:F1995