A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 贾联国 中级黑马   /  2012-4-28 04:32  /  2176 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

看视频的时候看到一个有意思的事,感觉很容易被忽略,就写了个小程序,大家分析一下原因吧~
  1. import java.util.*;
  2. public class TestSet
  3. {
  4.     public static void main(String[] args)
  5.     {
  6.         Set<Short> s=new HashSet<Short>();
  7.         for(short i=0;i<10;i++)
  8.         {
  9.             s.add(i);
  10.             s.remove(i-1);
  11.         }
  12.         System.out.println("size of s:"+s.size());
  13.     }
  14. }
复制代码
运行结果  size of s:10

3 个回复

倒序浏览
哈希集合操作元素时是通过元素的哈希值来索引的,
元素的哈希值是通过调用元素的hashcode得到的,
而除非自己重新定义这个方法否则默认是调用object的实现,
object的hashcode方法返回的哈希值是跟对象内存地址相关的,所以不同的对象的哈希值必然不同。
在楼主的代码里,调用add和remove时传入的是short基础类型的值,通过自动装箱,会产生一个新的Short类的对象,
而虽然对象的逻辑值相等但他们的哈希值不相等也被集合视为两个不同的元素,所以remove时传入的是通过自动装箱产生的新对象,
与add时传入的那个逻辑值相等的对象的哈希值不同所以一个都没有删除掉,所以最后size是10.
另外,如果集合元素类型是Integer,add和remove时传入的是int类型的值结果会不一样,最后size是1,
remove能删除成功是因为int类型的值在装箱成Integer对象时如果数值在一个字节的范围之内(-128~127)之间时,会先把对象缓存起来,
当下次又要把一个数值装成Integer对象时,会先去缓存的对象中去找如果有会直接把它拿来用不会产生一个新对象。

评分

参与人数 1技术分 +1 收起 理由
岳民喜 + 1

查看全部评分

回复 使用道具 举报
1楼的哥们。我也受教了
回复 使用道具 举报
在你的这段代码中,add()往集合中加入的是Short类型的数据,remove()删除的却是Integer类型的数据,所以才会出现最终打印结果为10,short类型的变量在运算过程中会自动提升类型为int,你在i-1前面进行强制类型转换,就可以成功remove掉i-1了,将s.remove(i-1)改为s.remove((short)(i-1))就行了。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马