关于Set的不确定性

Set是一个不包含重复元素的 Collection。(似乎我在废话)

让我们来看一段代码:

  int a=1,b=2,c=3,d=4,e=5,f=6;

  Set<Collection<Integer>> setClear = new HashSet<Collection<Integer>>();//定义一个用于测试的Set
		ArrayList<Integer> setClearInner  = new ArrayList<Integer>();//定义上述的用于放进Set中的元素

		setClearInner.add(a);
		setClearInner.add(b);
		setClearInner.add(c);
		setClear.add(setClearInner);

		setClearInner.clear();//清除setClearInner内的元素

		setClearInner.add(d);
		setClearInner.add(e);
		setClearInner.add(f);
		setClear.add(setClearInner);

		System.out.println("setClear ========" + setClear.toString());//输出setClear内的元素

		Iterator<Collection<Integer>> it = setClear.iterator();
		Collection<Integer> temp1 = it.next();
		Collection<Integer> temp2 = it.next();
                
  /*比较setClear内的两个元素,比输出它们各自的hash码*/
		System.out.println("equals ========" + temp1.equals(temp2));
		System.out.println("temp1.hashCode() ========" + temp1.hashCode());
		System.out.println("temp2.hashCode() ========" + temp2.hashCode());

 猜一下什么结果。false?看一下:

setClear ========[[4, 5, 6], [4, 5, 6]]
equals ========true
temp1.hashCode() ========33796
temp2.hashCode() ========33796

 没有看错,的确在Set里添加了同一元素!

 

在JDK API对Set的描述有这么一句话:

如果将可变对象用作 set 元素,那么必须极其小心。如果对象是 set 中某个元素,以一种影响 equals 比较的方式改变对象的值,那么 set 的行为就是不确定的。

正是这种不确定性,使我们往Set里添加了同一元素。

 

再看一段代码:

  int a=1,b=2,c=3;
		
		Set<Integer> setClear = new HashSet<Integer>();
		
		setClear.add(a);
		setClear.add(b);
		setClear.add(c);
		
		System.out.println("first:setClear ========" + setClear.toString());
		
		a=2;
		b=3;
		c=4;
		
		setClear.add(a);
		setClear.add(b);
		setClear.add(c);
		
		System.out.println("second:setClear ========" + setClear.toString());

 输出结果为:

first:setClear ========[1, 2, 3]
second:setClear ========[1, 2, 3, 4]

 Set只是添加了它原本没有包含的元素4。

 

说明Set的不确定性只用在对象上,不适合于基本数据类型。换一种说法,往Set里添加基本数据类型,添加的是基本数据类型的值;如果添加的是对象,则添加的时对象的一个引用,对象属性的改变,引起了Set的不确定性。

 

这个问题是在一个技术群里的一个人问起的,我和他讨论解决之后,决定把它发上来大家就流一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值