GVKun编程网logo

使用Comparable和Comparator比较通用类型(分别用comparable和comparator)

9

本篇文章给大家谈谈使用Comparable和Comparator比较通用类型,以及分别用comparable和comparator的知识点,同时本文还将给你拓展Comparable与Comparato

本篇文章给大家谈谈使用Comparable和Comparator比较通用类型,以及分别用comparable和comparator的知识点,同时本文还将给你拓展Comparable与Comparator比较的区别与联系、Comparable和Comparator接口、Comparable和Comparator的区别、Java Comparable和Comparator两种排序方式比较等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

使用Comparable和Comparator比较通用类型(分别用comparable和comparator)

使用Comparable和Comparator比较通用类型(分别用comparable和comparator)

我头疼,调试困难。我正在尝试比较两个通用值,以便可以根据值将它们插入到数组中进行排序。这是我第一次使用Comparable和Comparator界面,因此围绕这些问题的任何其他建议都是不错的选择。

这是我的班级设置方式:

public class SVStore<K, V extends Comparable<V>> implements Pairs<K, V>, Iterable<K>, Comparable<V>, Comparator<V> {

put()方法:

@Overridepublic V put(K key, V value) {    SVData<K, V> tab[] = table;    for (int i = 0; i < table.length - 1; i++) {        if (value.compareTo(tab[i].dataValue) <= 0) {            int index = i;            for( int j = index; j < size - 1; j++){                tab[j + 1] = tab[j];            }        }        tab[i].setDataKey(key);        tab[i].setDataValue(value);        size++;    }    return value;}

这些是我要实现的compareTo()和compare方法。

@Overridepublic int compareTo(V t) { return compare(t, this); }@Overridepublic int compare(V t, V t1) {    if (t.equals(t1)){        return 0;    } else if (t < t1){        return -1;    } else {        return 1;    }}

我遇到的第一个问题是compareTo()方法中的问题,它以“ this”为中心。该错误显示为“必填:V,V找到:V,SVStore”。我知道答案不是将“
this”转换为V。如何将其与该数组索引中的V进行比较?

我遇到的第二个问题是…} if(t
<t1){在compareTo()方法中。错误是“二进制运算符’<’的错误操作数类型,第一类型:V第二类型:V”。如果将两种类型都识别为V,为什么它是错误的操作数?

我认为所需的所有代码都在那里。我尝试使它们尽可能简洁,但是如果有人需要任何其他代码,我很乐意提供。干杯!

答案1

小编典典

多亏了Chrylis,Catalin Pol和Louis Wasserman的共同努力,我才知道我需要将课堂改正为:

public class SortedValueStore<K, V extends Comparable<? super V>> implements PairStore187<K, V>, Iterable<K>, {

我不再需要编写自己的compareTo()方法。

这成功了。我对Java相对较新,因此花了我一段时间才能理解每个人的说法,但是每个人都坚持不懈地努力。感谢大家的帮助!

Comparable与Comparator比较的区别与联系

Comparable与Comparator比较的区别与联系

1.接口Comparable<T> API

   参数类型:T ---可以与此对象进行比较的那些对象的类型

      此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo()方法被称为它的自然比较方法

      实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器

     Comparable也只有int compareTo(T object)一个方法。比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

复制代码
  1 public class Person implements Comparable<Person>
  2 {
  3     String name;
  4     int age;
  5     public Person(String name, int age)
  6     {
  7         super();
  8         this.name = name;
  9         this.age = age;
 10     }
 11     public String getName()
 12     {
 13         return name;
 14     }
 15     public int getAge()
 16     {
 17         return age;
 18     }
 19     @Override
 20     public int compareTo(Person p)
 21     {
 22         return this.age-p.getAge();
 23     }
 24     public static void main(String[] args)
 25     {
 26         Person[] people=new Person[]{new Person("wangwu", 18),new Person("zhaoliu", 19)};
 27         System.out.println("排序前");
 28         for (Person person : people)
 29         {
 30             System.out.print(person.getName()+":"+person.getAge());
 31         }
 32         Arrays.sort(people); 
33
System.out.println("\n排序后");
 34         for (Person person : people)
 35         {
 36             System.out.print(person.getName()+":"+person.getAge());
 37         }
 38     }
 39 }
复制代码

2.接口 Comparator<T> API

    强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator 传递给 sort 方法(如 Collections.sortArrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。

(1)int compare(T o1, T o2)

    比较用来排序的两个参数。根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。

    抛出异常:ClassCastException - 如果参数的类型不允许此 Comparator 对它们进行比较。

(2)boolean equals(Object obj)

    指示某个其他对象是否“等于”此 Comparator。此方法必须遵守 Object.equals(Object) 的常规协定。此外,仅当 指定的对象也是一个 Comparator,并且强行实施与此 Comparator 相同的排序时,此方法才返回 true。因此,comp1.equals(comp2) 意味着对于每个对象引用 o1 和 o2 而言,都存在 sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2))。

   注意, 重写 Object.equals(Object) 方法总是 安全的。然而,在某些情况下,重写此方法可以允许程序确定两个不同的 Comparator 是否强行实施了相同的排序,从而提高性能。

  若一个类要实现Comparator 接口:它一定要实现compare(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。

复制代码
  1 //定义一个比较器
  2 public class PersonCompartor implements Comparator<Person>
  3 {
  4     @Override
  5     public int compare(Person o1, Person o2)
  6     {
  7         return o1.getAge()-o2.getAge();
  8     }
  9 }
 10 
 11 public class Person
 12 {
 13     String name;
 14     int age;
 15     public Person(String name, int age)
 16     {
 17         super();
 18         this.name = name;
 19         this.age = age;
 20     }
 21     public String getName()
 22     {
 23         return name;
 24     }
 25     public int getAge()
 26     {
 27         return age;
 28     }
 29     public static void main(String[] args)
 30     {
 31         Person[] people=new Person[]{new Person("xujian", 20),new Person("xiewei", 10)};
 32         System.out.println("排序前");
 33         for (Person person : people)
 34         {
 35             System.out.print(person.getName()+":"+person.getAge());
 36         }
//创建比较器参数PersonCompartor
 37         Arrays.sort(people,new PersonCompartor()); 
38
System.out.println("\n排序后");
 39         for (Person person : people)
 40         {
 41             System.out.print(person.getName()+":"+person.getAge());
 42         }
 43     }
 44 }
复制代码

 

3.Comparator与Comparable比较

(1)Comparable 接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序.

    Comparable是 定义在 Person类的内部称为“内部排序”,是一种简单的方式,需要修改源代码。

Arrays.sort(people);

(2)Comparator 是比较器,排序时,需要新建比较器对象,将比较器和对象一起传递过去就可以比大小,可称为“外部排序”。

Comparator 是定义在Person的外部的, 此时我们的Person类的结构不需要有任何变化。并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

Arrays.sort(people,new PersonCompartor());

 

Comparable和Comparator接口

Comparable和Comparator接口

java中通过接口实现两个对象的比较,常用的就是Comparable和Comparator接口。

Comparable:位于java.lang包

Comparator:位于java.util包

排序通常使用的方法是:

Collections.sort(List<T> list)

或者

Collections.sort(List<T> list, Comparator<? super T> c)

根据排序的方法可以看到,一种是对象本身实现了排序,一种是实现Comparator接口的排序。具体使用如下所示:

一、Comparable:

Comparable接口将比较代码嵌入需要进行比较的类的自身代码中。此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序,类的CompareTo方法被称为它的自然比较方法。实现此接口的对象列表可以通过Collections.sort(和Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射表中的键或有序集合中的元素,无需指定比较器。

示例

/**
 * 因为要实现对ConsumInfo对象的排序,所以ConsumInfo类中要实现Comparable接口
 * 也就是要实现compareTo()方法
 */
public class ConsumInfo implements Comparable<ConsumInfo> {
    private int uid;
    private String name;
    private double price;
    private Date datetime;

    public ConsumInfo() {
    }

    public ConsumInfo(int uid, String name, double price, Date datetime) {
        this.uid = uid;
        this.name = name;
        this.price = price;
        this.datetime = datetime;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Date getDatetime() {
        return datetime;
    }

    public void setDatetime(Date datetime) {
        this.datetime = datetime;
    }

    @Override
    public String toString() {
        return "ConsumInfo{" +
                "uid=" + uid +
                ", name=''" + name + ''\'''' +
                ", price=" + price +
                ", datetime=" + datetime +
                ''}'';
    }

    public int compareTo(ConsumInfo o) {
       //升序排序
        if (price < o.price){
            return -1;
        }
        if (price > o.price){
            return 1;
        }
        if (price == o.price){
            if (uid < o.uid){
                return -1;
            }
            if (uid > o.uid){
                return 1;
            }
        }
        return 0;
    }
}

测试类:
public class ConsumIofoTest {
    public static void main(String[] args) {
        ConsumInfo consumInfo1 = new ConsumInfo(100, "consumInfo1", 400.0,new Date());
        ConsumInfo consumInfo2 = new ConsumInfo(200, "consumInfo1", 200.0,new Date());
        ConsumInfo consumInfo3 = new ConsumInfo(300, "consumInfo1", 100.0,new Date());
        ConsumInfo consumInfo4 = new ConsumInfo(400, "consumInfo1", 700.0,new Date());
        ConsumInfo consumInfo5 = new ConsumInfo(500, "consumInfo1", 800.0,new Date());
        ConsumInfo consumInfo6 = new ConsumInfo(600, "consumInfo1", 300.0,new Date());
        ConsumInfo consumInfo7 = new ConsumInfo(700, "consumInfo1", 900.0,new Date());
        ConsumInfo consumInfo8 = new ConsumInfo(800, "consumInfo1", 400.0,new Date());

        List<ConsumInfo> list = new ArrayList<ConsumInfo>();
        list.add(consumInfo1);
        list.add(consumInfo2);
        list.add(consumInfo3);
        list.add(consumInfo4);
        list.add(consumInfo5);
        list.add(consumInfo6);
        list.add(consumInfo7);
        list.add(consumInfo8);
        System.out.println("排序前");
        for (ConsumInfo consumInfo : list){
            System.out.println(consumInfo);
        }
        Collections.sort(list);
        System.out.println("排序后");
        for (ConsumInfo consumInfo :list){
            System.out.println(consumInfo);
        }
    }
}

二、Comparator:

Comparator接口在一个独立的类中实现。如果前期类的设计没有考虑到类的Compare问题而没有实现Comparable接口,后期可以通过Comparator接口实现比较算法进行排序。

示例:

//要进行比较的类
public class ConsumInfo{
    private int uid;
    private String name;
    private double price;
    private Date datetime;

    public ConsumInfo() {
    }

    public ConsumInfo(int uid, String name, double price, Date datetime) {
        this.uid = uid;
        this.name = name;
        this.price = price;
        this.datetime = datetime;
    }

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public Date getDatetime() {
        return datetime;
    }

    public void setDatetime(Date datetime) {
        this.datetime = datetime;
    }

    @Override
    public String toString() {
        return "ConsumInfo{" +
                "uid=" + uid +
                ", name=''" + name + ''\'''' +
                ", price=" + price +
                ", datetime=" + datetime +
                ''}'';
    }
}

//实现Comparator接口的比较器
public class ComparatorConsunInfo implements Comparator<ConsumInfo> {
    public int compare(ConsumInfo o1, ConsumInfo o2) {
        if (o1.getPrice() > o2.getPrice()){
            return 1;
        }

        if (o1.getPrice() < o2.getPrice()){
            return -1;
        }

        if (o1.getPrice() == o2.getPrice()){
            if (o1.getUid() > o2.getUid()){
                return 1;
            }

            if (o1.getUid() < o2.getUid()){
                return -1;
            }
        }
        return 0;
    }
}

//测试类
public class ConsumIofoTest {
    public static void main(String[] args) {
        ConsumInfo consumInfo1 = new ConsumInfo(100, "consumInfo1", 400.0,new Date());
        ConsumInfo consumInfo2 = new ConsumInfo(200, "consumInfo1", 200.0,new Date());
        ConsumInfo consumInfo3 = new ConsumInfo(300, "consumInfo1", 100.0,new Date());
        ConsumInfo consumInfo4 = new ConsumInfo(400, "consumInfo1", 700.0,new Date());
        ConsumInfo consumInfo5 = new ConsumInfo(500, "consumInfo1", 800.0,new Date());
        ConsumInfo consumInfo6 = new ConsumInfo(600, "consumInfo1", 300.0,new Date());
        ConsumInfo consumInfo7 = new ConsumInfo(700, "consumInfo1", 900.0,new Date());
        ConsumInfo consumInfo8 = new ConsumInfo(800, "consumInfo1", 400.0,new Date());

        List<ConsumInfo> list = new ArrayList<ConsumInfo>();
        list.add(consumInfo1);
        list.add(consumInfo2);
        list.add(consumInfo3);
        list.add(consumInfo4);
        list.add(consumInfo5);
        list.add(consumInfo6);
        list.add(consumInfo7);
        list.add(consumInfo8);
        System.out.println("排序前");
        for (ConsumInfo consumInfo : list){
            System.out.println(consumInfo);
        }
        ComparatorConsunInfo comparatorConsunInfo = new ComparatorConsunInfo();
        Collections.sort(list,comparatorConsunInfo);
        System.out.println("排序后");
        for (ConsumInfo consumInfo :list){
            System.out.println(consumInfo);
        }
    }
}


今天想对一个集合进行排序,看了自己写的文章,竟然没看懂。因为说到排序,自然有升序和降序。但是上述篇幅都没有说到。。。。。

现在补充一下:

对于Comparable方式来说:

public int compareTo(BeanClass bc) {
		//return this.para - bc.para; //升序
		return bc.para-this.para; //降序
	}

对于Comparator:方式来说

  @Override
    public int compare(BeanClass o1, BeanClass o2) {
        //return o1.para-o2.para;  //升序
        return o2.para-o1.para;  //降序
    }

 

Comparable和Comparator的区别

Comparable和Comparator的区别

Comparable

Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较,则依赖compareTo方法的实现,compareTo方法也被称为自然比较方法。如果开发者add进入一个Collection的对象想要Collections的sort方法帮你自动进行排序的话,那么这个对象必须实现Comparable接口。compareTo方法的返回值是int,有三种情况:

1、比较者大于被比较者(也就是compareTo方法里面的对象),那么返回正整数

2、比较者等于被比较者,那么返回0

3、比较者小于被比较者,那么返回负整数

写个很简单的例子:

public class Domain implements Comparable<Domain>
{
    private String str;

    public Domain(String str)
    {
        this.str = str;
    }

    public int compareTo(Domain domain)
    {
        if (this.str.compareTo(domain.str) > 0)
            return 1;
        else if (this.str.compareTo(domain.str) == 0)
            return 0;
        else 
            return -1;
    }
    
    public String getStr()
    {
        return str;
    }
}
public static void main(String[] args)
    {
        Domain d1 = new Domain("c");
        Domain d2 = new Domain("c");
        Domain d3 = new Domain("b");
        Domain d4 = new Domain("d");
        System.out.println(d1.compareTo(d2));
        System.out.println(d1.compareTo(d3));
        System.out.println(d1.compareTo(d4));
    }

运行结果为:

 

0
1
-1

 

注意一下,前面说实现Comparable接口的类是可以支持和自己比较的,但是其实代码里面Comparable的泛型未必就一定要是Domain,将泛型指定为String或者指定为其他任何任何类型都可以----只要开发者指定了具体的比较算法就行。

 

Comparator

Comparator可以认为是是一个外比较器,个人认为有两种情况可以使用实现Comparator接口的方式:

1、一个对象不支持自己和自己比较(没有实现Comparable接口),但是又想对两个对象进行比较

2、一个对象实现了Comparable接口,但是开发者认为compareTo方法中的比较方式并不是自己想要的那种比较方式

Comparator接口里面有一个compare方法,方法有两个参数T o1和T o2,是泛型的表示方式,分别表示待比较的两个对象,方法返回值和Comparable接口一样是int,有三种情况:

1、o1大于o2,返回正整数

2、o1等于o2,返回0

3、o1小于o3,返回负整数

写个很简单的例子,上面代码的Domain不变(假设这就是第2种场景,我对这个compareTo算法实现不满意,要自己写实现):

 

public class DomainComparator implements Comparator<Domain>
{
    public int compare(Domain domain1, Domain domain2)
    {
        if (domain1.getStr().compareTo(domain2.getStr()) > 0)
            return 1;
        else if (domain1.getStr().compareTo(domain2.getStr()) == 0)
            return 0;
        else 
            return -1;
    }
}

 

public static void main(String[] args)
{
    Domain d1 = new Domain("c");
    Domain d2 = new Domain("c");
    Domain d3 = new Domain("b");
    Domain d4 = new Domain("d");
    DomainComparator dc = new DomainComparator();
    System.out.println(dc.compare(d1, d2));
    System.out.println(dc.compare(d1, d3));
    System.out.println(dc.compare(d1, d4));
}

当然因为泛型指定死了,所以实现Comparator接口的实现类只能是两个相同的对象(不能一个Domain、一个String)进行比较了,因此实现Comparator接口的实现类一般都会以"待比较的实体类+Comparator"来命名

 

总结

总结一下,两种比较器Comparable和Comparator,后者相比前者有如下优点:

1、如果实现类没有实现Comparable接口,又想对两个类进行比较(或者实现类实现了Comparable接口,但是对compareTo方法内的比较算法不满意),那么可以实现Comparator接口,自定义一个比较器,写比较算法

2、实现Comparable接口的方式比实现Comparator接口的耦合性 要强一些,如果要修改比较算法,要修改Comparable接口的实现类,而实现Comparator的类是在外部进行比较的,不需要对实现类有任何修 改。从这个角度说,其实有些不太好,尤其在我们将实现类的.class文件打成一个.jar文件提供给开发者使用的时候。实际上实现Comparator 接口的方式后面会写到就是一种典型的策略模式

当然,这不是鼓励用Comparator,意思是开发者还是要在具体场景下选择最合适的那种比较器而已。

 

Java Comparable和Comparator两种排序方式比较

Java Comparable和Comparator两种排序方式比较

实现这两个排序接口其实写法上是一样的,当我们需要对单元类进行排序的时候需要写一下泛型实现接口,如下:


//实现Comparable接口
public class PersonBean implements Comparable<PersonBean> {

    public int age;

    //这是降序排列,倒序的话写法是another.age-age
    @Override
    public int compareTo(PersonBean another) {
        return age-another.age;
    }
}

//实现Comparator接口
public class PersonBean implements Comparator<PersonBean> {

    public int age;

    //这是升序排列,降序排列是rhs.age-lhs.age
    @Override
    public int compare(PersonBean lhs, PersonBean rhs) {
        return lhs.age-rhs.age;
    }
}

对列表进行排序的时候,写法有写不同,Comparator需要单独传入参数,


    PersonBean bean1 = new PersonBean();
        bean1.age = 1;
        PersonBean bean2 = new PersonBean();
        bean2.age = 2;
        PersonBean bean3 = new PersonBean();
        bean3.age = 3;
        PersonBean bean4 = new PersonBean();
        bean4.age = 4;
        List<PersonBean> beanList = new ArrayList<>();
        beanList.add(bean3);
        beanList.add(bean2);
        beanList.add(bean4);
        beanList.add(bean1);
        Collections.sort(beanList);//这是实现Comparable的排序写法
        Collections.sort(beanList,new PersonBean());//这是实现Comparator的排序写法

        for (int i = 0; i < beanList.size(); i++) {
            Log.e("年龄",beanList.get(i).age+"");
        }

关于使用Comparable和Comparator比较通用类型分别用comparable和comparator的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Comparable与Comparator比较的区别与联系、Comparable和Comparator接口、Comparable和Comparator的区别、Java Comparable和Comparator两种排序方式比较等相关知识的信息别忘了在本站进行查找喔。

本文标签: