在看Java从入门到精通的过程中遇到这样一道习题:定义Student类,该类不实现Comparable接口,定义一个Comparator类比较两个Student对象所在班级名称和名字,班级名相同时用名字进行排序,使用TreeSet观察排序结果。
这是我最初写的程序和运行结果截图
package javautil;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.Comparator;
class MyCompare implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
String strclass1 = o1.getClassid();
String strclass2 = o2.getClassid();
String strname1 = o1.getName();
String strname2 = o2.getName();
if((strclass1.compareTo(strclass2))!=0) {
return strclass1.compareTo(strclass2);
} else {
return strname1.compareTo(strname2);
}
}
}
public class shizhan20_2 {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(new MyCompare());
ts.add(new Student("李四","3班"));
ts.add(new Student("张三","1班"));
ts.add(new Student("李四","1班"));
ts.add(new Student("张三","2班"));
ts.add(new Student("王五","1班"));
//System.out.println(ts);
Iterator<Student> ito = ts.iterator();
while(ito.hasNext()) {
Student s = ito.next();
System.out.println(s.getClassid()+","+s.getName());
}
}
}
很明显,程序运行结果并不符合题目要求,他并没有实现当班级名称相同时对学生姓名进行排序的功能。接下来我开始Debug运行程序,发现程序并没有漏洞,对错误原因也是百思不得其解,在多处写了测试输出后也看不出任何端倪,最后尝试吧所有的名字改成拼音,下面是改成拼音以后的源程序以及运行结果截图:
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(new MyCompare());
ts.add(new Student("LiSi","3班"));
ts.add(new Student("ZhangSan","1班"));
ts.add(new Student("LiSi","1班"));
ts.add(new Student("ZhangSan","2班"));
ts.add(new Student("WangWu","1班"));
//System.out.println(ts);
Iterator<Student> ito = ts.iterator();
while(ito.hasNext()) {
Student s = ito.next();
System.out.println(s.getClassid()+","+s.getName());
}
}
运行结果是完全符合标准的,这样就大概猜出了错误原因,就是compareTo( )方法在对字符串进行比较时,比较的是Unicode码,并不能对汉字进行准确的排序,所以汉字比较时会出现比较混乱的结果。当然,Java自然有他的解决方式,通过上网搜和查API文档,找到了一种解决办法,java.text.Collator类中有一个getInstance(Locale desiredLocale) 方法可以解决对汉字排序的问题,这样我们就需要重写compare( )方法,修改后的最终完整代码和运行结果截图如下:
public class Student {
private String name=null;
private String classid=null;
public Student(String name,String classid) {
this.classid=classid;
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setClassid(String classid) {
this.classid = classid;
}
public String getClassid() {
return classid;
}
}
import java.util.Iterator;
import java.util.Locale;
import java.util.TreeSet;
import java.text.Collator;
import java.util.Comparator;
class MyCompare implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
String strclass1 = o1.getClassid();
String strclass2 = o2.getClassid();
String strname1 = o1.getName();
String strname2 = o2.getName();
if((strclass1.compareTo(strclass2))!=0) {
return strclass1.compareTo(strclass2);
} else {
Collator instance = Collator.getInstance(Locale.CHINA);
return instance.compare(strname1, strname2);
}
}
}
public class shizhan20_2 {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(new MyCompare());
ts.add(new Student("李四","3班"));
ts.add(new Student("张三","1班"));
ts.add(new Student("李四","1班"));
ts.add(new Student("张三","2班"));
ts.add(new Student("王五","1班"));
//System.out.println(ts);
Iterator<Student> ito = ts.iterator();
while(ito.hasNext()) {
Student s = ito.next();
System.out.println(s.getClassid()+","+s.getName());
}
}
}