本篇文章给大家谈谈使用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的区别
- Java 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比较的区别与联系
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.sort
或 Arrays.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接口
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
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两种排序方式比较
实现这两个排序接口其实写法上是一样的,当我们需要对单元类进行排序的时候需要写一下泛型实现接口,如下:
//实现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两种排序方式比较等相关知识的信息别忘了在本站进行查找喔。
本文标签: