一 TreeSet类的误用一
1 代码示例
import java.util.*;
class Err{}
public class TreeSetErrorTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
// 向TreeSet集合中添加两个Err对象
ts.add(new Err());
ts.add(new Err()); //①
}
}
2 运行结果
E:\test\Java\Java8\Java8\src>java TreeSetErrorTest
Exception in thread "main" java.lang.ClassCastException: Err cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at TreeSetErrorTest.main(TreeSetErrorTest.java:11)
3 代码说明
上面代码试图向TreeSet集合中添加两个Err对象,添加第一个对象时,TreeSet里没有任何元素,所以不会出现任何问题,当向TreeSet集合添加第二个Err对象时,TreeSet就会调用该对象的compareTo(Object obj)方法与集合中的其他元素进行比较,如果对应的类没有实现Comparable接口,则会引发ClassCastException异常。因此上面程序将会在①代码处引发该异常。
二 TreeSet类的误用二
1 代码示例
import java.util.*; public class TreeSetErrorTest2 { public static void main(String[] args) { TreeSet ts = new TreeSet(); // 向TreeSet集合中添加两个对象 ts.add(new String("Java")); //ts.add(new String("Linux")); ts.add(new Date()); // ① System.out.println(ts); } }
2 运行结果
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Date
at java.util.Date.compareTo(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at java.util.TreeSet.add(Unknown Source)
at TreeSetErrorTest2.main(TreeSetErrorTest2.java:12)
3 代码说明
从运行结果来看,因为添加的两个对象的类型不一致,所以抛出了异常。如果希望TreeSet正常工作,TreeSet只能添加同一种类型的对象。
三 TreeSet类的误用三
1 代码示例
import java.util.*; class Z implements Comparable { int age; public Z(int age) { this.age = age; } // 重写equals()方法,总是返回true public boolean equals(Object obj) { return true; } // 重写了compareTo(Object obj)方法,总是返回1 public int compareTo(Object obj) { return 1; } } public class TreeSetTest2 { public static void main(String[] args) { TreeSet set = new TreeSet(); Z z1 = new Z(6); set.add(z1); // 第二次添加同一个对象,输出true,表明添加成功 System.out.println(set.add(z1)); //① // 下面输出set集合,将看到有两个元素 System.out.println(set); // 修改set集合的第一个元素的age变量 ((Z)(set.first())).age = 9; // 输出set集合的最后一个元素的age变量,将看到也变成了9 System.out.println(((Z)(set.last())).age); } }2 运行结果
true
[Z@1db9742, Z@1db9742]
9
3 代码说明
从运行结果来看,可以得出一个规则:如果两个对象通过equals()方法比较返回true时,这两个对象通过compareTo()方法比较应该返回0。
四 TreeSet类的误用四
1 代码示例
import java.util.*; class R implements Comparable { int count; public R(int count) { this.count = count; } public String toString() { return "R[count:" + count + "]"; } // 重写equals方法,根据count来判断是否相等 public boolean equals(Object obj) { if (this == obj) { return true; } if(obj != null && obj.getClass() == R.class) { R r = (R)obj; return r.count == this.count; } return false; } // 重写compareTo方法,根据count来比较大小 public int compareTo(Object obj) { R r = (R)obj; return count > r.count ? 1 : count < r.count ? -1 : 0; } } public class TreeSetTest3 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new R(5)); ts.add(new R(-3)); ts.add(new R(9)); ts.add(new R(-2)); // 打印TreeSet集合,集合元素是有序排列的 System.out.println(ts); // ① // 取出第一个元素 R first = (R)ts.first(); // 对第一个元素的count赋值 first.count = 20; // 取出最后一个元素 R last = (R)ts.last(); // 对最后一个元素的count赋值,与第二个元素的count相同 last.count = -2; // 再次输出将看到TreeSet里的元素处于无序状态,且有重复元素 System.out.println(ts); // ② // 删除实例变量被改变的元素,删除失败 System.out.println(ts.remove(new R(-2))); // ③ System.out.println(ts); // 删除实例变量没有被改变的元素,删除成功 System.out.println(ts.remove(new R(5))); // ④ System.out.println(ts); } }2 运行结果
E:\test\Java\Java8\Java8\src>java TreeSetTest3
[R[count:-3], R[count:-2], R[count:5], R[count:9]]
[R[count:20], R[count:-2], R[count:5], R[count:-2]]
false
[R[count:20], R[count:-2], R[count:5], R[count:-2]]
true
[R[count:20], R[count:-2], R[count:-2]]
3 代码说明
为了让程序更加健壮,推荐不要修改TreeSet集合中元素的关键实例变量。