Java TreeSet插入对象疑问

首先是Customer类定义:

package com.lzw;
import java.util.Comparator;
public class Customer implements Comparator<Object>{
private long id
private String name;
public Customer(String name,long id){
this.id=id;
this.name=name;
}
public int compare(Object o1,Object o2){
Customer c1=(Customer)o1;
Customer c2=(Customer)o2;
if(c1.getName().compareTo(c2.getName())>0) return -1;
if(c1.getName().compareTo(c2.getName())<0) return 1;
return 0;
}
public String getName(){
return name;
}
public long getId(){
return this.id;
}
}

然后是CustomerComparator类定义:

package com.lzw;
import com.lzw.Customer;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;
public class CustomerComparator implements Comparator<Object>{
public int compare(Object o1,Object o2){
Customer c1=(Customer)o1;
Customer c2=(Customer)o2;
if(c1.getName().compareTo(c2.getName())>0) return -1;
if(c1.getName().compareTo(c2.getName()) return 0;
}
public static void main(String[] args) {
// TODO 自动生成的方法存根
TreeSet<Customer> set=new TreeSet<Customer>(new CustomerComparator());
Customer c1=new Customer("Andy",109201041);
Customer c2=new Customer("JACK",109207042);
Customer c3=new Customer("MIKE",109207043);
Customer c4=new Customer("Kath",109207044);
set.add(c1);
set.add(c2);
set.add(c3);
set.add(c4);
Iterator it=set.iterator();
while(it.hasNext()) {
Customer customer=(Customer)it.next();
System.out.println(customer.getName()+" "+customer.getId());
}
}
}

实例化对象:

  TreeSet<Customer> set=new TreeSet<Customer>(new CustomerComparator());

如果改成:

 TreeSet<customer> set=new TreeSet<customer>();

在 set.add(c1);语句时报错误:
Exception in thread "main" java.lang.ClassCastException: com.lzw.Customer cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1290)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at com.lzw.CustomerComparator.main(CustomerComparator.java:24)
问题:1、请问为什么会这样?2、TreeSet的集合元素是Customer对象,我也在Customer类实现了compare的方法,为什么在add的时候不是调用这个方法而是在CustomerComparator实现的compare的方法?

3个回答

treeset这个类,两种方式初始化,有指定比较器 和 没有指定比较器。
查看treeset这个类,父类是treemap,在执行add方法时,其实就是treemap的add。
源码要求,要么传一个comparator比较器给treeset;要么不传比较器时,要求元素类要实现comparable接口。
注:区分
Comparator 比较器的比较方法为 compare
Comparable 的比较方法为compareTo

yllcxsj
yllcxsj 回复hgl125:楼上的意思是,TreeSet的实现底层是用TreeMap来存储数据的。而在TreeMap的实现实际上就是一个二叉树,它在存储对象的时候,会调用比较器来安放对象的位置。
5 年多之前 回复
hgl125
hgl125 1、我查看treeset的定义是public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable怎么是treemap的子类呢?2、new的时候调用的是treeset的那个构造函数?
5 年多之前 回复
 public class Customer implements Comparator
 改成
 public class Customer implements Comparable

 如果treeset中通过构造初始化的,Comparator。
 如果构造函数没有初始化Comparator,那么add进入的对象必须实现Comparable才行,不然无法转化对象。
danielinbiti
danielinbiti 回复hgl125: 你找一下java treeset的源码就行了。看一下put的逻辑,应该不复杂
5 年多之前 回复
hgl125
hgl125 回复danielinbiti: 具体是怎么判断法,有源码吗?
5 年多之前 回复
danielinbiti
danielinbiti 回复hgl125: add的时候treeset是有判断的,如果初始化了Comparator,那么按照Comparator的compare方法进行插入的对象比较。如果没有Comparator,则add的对象需要实现Comparable,然后通过compareto进行对象比较。
5 年多之前 回复
hgl125
hgl125 怎么就调用了CustomerComparator类的compare方法
5 年多之前 回复
hgl125
hgl125 问题是如果把Customer的继承注销
5 年多之前 回复

都写着class cast exception了
java.lang.ClassCastException: com.lzw.Customer cannot be cast to java.lang.Comparable

強转出错,新手错误啊

hgl125
hgl125 大神知道你厉害了,能解释TreeSet<Customer> set=new TreeSet<Customer>(new CustomerComparator());怎么就和CustomerComparator类关联起来了呢?
5 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐