欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TreeSet类的常见误用

程序员文章站 2022-05-14 13:08:00
...

一 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
[[email protected], [email protected]]
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集合中元素的关键实例变量。

相关标签: TreeSet