黑马程序员技术交流社区

标题: TreeSet比较器问题 [打印本页]

作者: 徐然    时间: 2012-5-4 16:51
标题: TreeSet比较器问题
import java.util.*;
class Student
{
private String name;
private int age;
private int num;
Student(String name, int age,int num)
{
  this.name=name;
  this.age=age;
  this.num=num;
}

public String getName()
{
  return name;
}
public int getAge()
{
  return age;
}
public int getNum()
{
  return num;
}
}
class StuMessage
{
public static void main(String[] args)
{
  TreeSet<Student> al = new TreeSet<Student>(new StuNumComparator());                 //这里比较器不能实例化,编译提示比较器需要静态
  al.add(new Student("zhangsan",20,80));
  al.add(new Student("lisi",18,70));
   
  for(Iterator<Student> it = al.iterator();it.hasNext(); )
  {
   Student s = it.next();   
   System.out.println(s.getName()+","+s.getAge()+","+s.getNum());
  }
}

class StuNumComparator implements Comparator<Student>                         //这个是按照号码排列的比较器
{
public int compare(Student s1,Student s2)
{
  
  int temp = new Integer(s2.getNum()).compareTo(new Integer(s1.getNum()));
  if(temp==0)  
   return s1.getName().compareTo(s2.getName());
  return temp;
}
}
}

为什么类的实例化过程需要类静态呢,搞晕了,貌似跟没有复写HashCoad和equals又没什么关系
求详解。
(这是完整代码,比较器加上static就可以编译成功)

作者: 姚鑫    时间: 2012-5-4 17:15
因为你把StuNumComparator定义成StuMessage的内部类了,把StuNumComparator放在外面就好了。
毕老师的视频有讲过
当外部类中的静态方法访问内部类时,内部类也必须是静态的。
作者: 陈苓    时间: 2012-5-4 17:16
TreeSet底层使用的是二叉树结构,所以与HashCoad和equals没有关系。只有HashSet需要覆盖HashCoad和equals这两个方法。
作者: 魏征    时间: 2012-5-4 17:50
TreeSet集合类底层是二叉树结构,底层调用的是CompareTo,如果传入Comparator比较器,调用的是compare(obj1,obj2)方法,但在自定义类时有可能被几个不同的集合类引用,所以要把自定义类中的内容设定的更全面,但在TreeSet集合类中底层不调用的。
当外部类中的静态方法访问了内部类时内部类也得修饰static,
或者TreeSet<Student> al = new TreeSet<Student>(new StuMessage().new StuNumComparator());   
作者: 许涛    时间: 2012-5-4 18:42
比较器写成了内部类的形式,被主函数调用,而主函数是静态的,所以比较器也要静态修饰

你把比较器定义成一个独立的类,就不需要静态了
作者: 袁冬梅    时间: 2012-5-4 18:56
本帖最后由 袁冬梅 于 2012-5-4 19:01 编辑
  1. class StuMessage
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.           TreeSet<Student> al = new TreeSet<Student>(new StuMessage().new StuNumComparator());  
  6.           /*
  7.           不多说,这是内部类的原因造成的;
  8.           其一,StuNumComparator这个类被你放在了StuMessage类中,那么StuNumComparator类就是StuMessage类中的一个成员变量
  9.           其二,你这个类是在main方法中被调用,而【静态方法中只能直接使用它所属类中的静态成员】。
  10.           其三,你创建StuNumComparator对象的时候用的是new StuNumComparator(),这样的话,其实是暗示编译器你这个类是静态类,所以,编译器才会要求你把这个类变成静态的,这样的话,就可以在静态函数中直接new你的比较器类了
  11.           其四,还是静态方法中使用非静态成员的方式,创建对象。也就是说,你这个比较器类不创建成静态类也可以,不过,你得用我给你的这个格式对你的比较器类创建对象。new StuMessage().new StuNumComparator()。先创建外部类StuMessage的对象,然后在创建这个对象中的比较器类的对象,然后你就可以使用了。
  12.          
  13.           这些内容都是内部类中的内容,如果我讲的还不清楚的话,建议你回头去看看毕老师的内部类部分的视频。O(∩_∩)O~希望对你有帮助。

  14.           */
  15.           al.add(new Student("zhangsan",20,80));
  16.           al.add(new Student("lisi",18,70));
  17.             
  18.           for(Iterator<Student> it = al.iterator();it.hasNext(); )
  19.           {
  20.            Student s = it.next();   
  21.            System.out.println(s.getName()+","+s.getAge()+","+s.getNum());
  22.           }
  23.         }

  24.         class StuNumComparator implements Comparator<Student>//这个是按照号码排列的比较器
  25.         {
  26.                 public int compare(Student s1,Student s2)
  27.                 {
  28.                   
  29.                   int temp = new Integer(s2.getNum()).compareTo(new Integer(s1.getNum()));
  30.                   if(temp==0)  
  31.                    return s1.getName().compareTo(s2.getName());
  32.                   return temp;
  33.                 }
  34.         }
  35. }
复制代码

作者: 何阳    时间: 2012-5-4 22:28
import java.util.*;
class Student
{
private String name;
private int age;
private int num;
Student(String name, int age,int num)
{
  this.name=name;
  this.age=age;
  this.num=num;
}

public String getName()
{
  return name;
}
public int getAge()
{
  return age;
}
public int getNum()
{
  return num;
}
}
class StuMessage
{
public static void main(String[] args)
{
  TreeSet<Student> al = new TreeSet<Student>(new StuNumComparator());                 //这里比较器不能实例化,编译提示比较器需要静态
  al.add(new Student("zhangsan",20,80));
  al.add(new Student("lisi",18,70));
   
  for(Iterator<Student> it = al.iterator();it.hasNext(); )
  {
   Student s = it.next();   
   System.out.println(s.getName()+","+s.getAge()+","+s.getNum());
  }
}

class StuNumComparator implements Comparator<Student>                         //这个是按照号码排列的比较器
{
public int compare(Student s1,Student s2)
{
  
  int temp = new Integer(s2.getNum()).compareTo(new Integer(s1.getNum()));
  if(temp==0)  
   return s1.getName().compareTo(s2.getName());
  return temp;
}
}
}
//其实你的代码并没有错,你只不过将构造器的类写在class StuMessage里面了
/*E:\java>javac Demo2.java
Demo2.java:31: 无法从静态上下文中引用非静态 变量 this
  TreeSet<Student> al = new TreeSet<Student>(new StuNumComparator());
      //这里比较器不能实例化,编译提示比较器需要静态
                                             ^
1 错误

E:\java>javac Demo2.java

E:\java>java StuMessage
zhangsan,20,80
lisi,18,70
*/

作者: 徐然    时间: 2012-5-8 10:55
哦哦,还真是写成内部类了,却没发现,应该是手误
谢谢各位了




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2