walterwing
日历
<
2008年11月
>
日
一
二
三
四
五
六
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
统计
随笔 - 12
文章 - 1
评论 - 7
引用 - 0
导航
BlogJava
首页
发新随笔
发新文章
联系
聚合
管理
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
(1)
给我留言
查看公开留言
查看私人留言
随笔分类
Java基础(9)
(rss)
大千世界(2)
(rss)
随笔档案
2009年2月 (2)
2008年11月 (2)
2008年10月 (2)
2008年7月 (7)
搜索
最新评论
1. re: java线程基本知识小结
very good
--very good
2. re: (转载)高科技公司的摇篮 — 斯坦福大学[未登录]
@与你同飞
面包会有的:) 虽然有生之年可能看不到国内大学也能跻身世界前列,但我们也要对自己有信心,哪怕路途再遥远,也要努力向前
--Wing
3. re: (转载)高科技公司的摇篮 — 斯坦福大学
差距啊,差距,什么是差距?这就是差距!
--与你同飞
4. re: 一道小而精巧的笔试题——Set、equals、类型转换……
评论内容较长,点击标题查看
--This is Wing
5. re: 一道小而精巧的笔试题——Set、equals、类型转换……
请讲讲
removeEntryForKey
这段代码吧,
我是新手,看不懂。
--sclsch
阅读排行榜
1. 对象的序列化和反序列化(转载+原创)(4889)
2. java线程基本知识小结(3350)
3. (转载)高科技公司的摇篮 — 斯坦福大学(642)
4. 一道小而精巧的笔试题——Set、equals、类型转换……(639)
5. The Collections Framework (摘要)- Part 4(557)
评论排行榜
1. 一道小而精巧的笔试题——Set、equals、类型转换……(3)
2. (转载)高科技公司的摇篮 — 斯坦福大学(2)
3. java线程基本知识小结(1)
4. 静态Proxy与动态Proxy用法浅析(0)
5. The Collections Framework (摘要)- Part 4(0)
一道小而精巧的笔试题——Set、equals、类型转换……
题目:
public
class
SetSize
{
public
static
void
main(string[] args)
{
Set
<
Short
>
set
=
new
HashSet
<
Short
>
();
for
(
short
i
=
0
; i
<
10
; i
++
)
{
set.add(i);
set.remove(i
-
1
);
}
System.out.println(set.size());
}
}
上面代码输出结果为10,为什么?
题目乍一看很简单,不就是一个HashSet么,但看完了题目又觉得困惑:对啊,怎么会是10?真难为自己还特意花了一些时间学习Java的Collection Framework,居然连这么小的一个题目都吃不透,汗颜啊……
看了半天,没有思路,跳过去做其他题,待到收卷前10分钟,不甘心,再回过头来看这道题。发现一个值得怀疑的地方:Set<Short> set = ……
为什么要特意设定是Short?再看到下面的i - 1,马上感觉到似乎和类型转换有关。
目前可以肯定的是:
1. set存储的元素是Short类型
2. 调用remove方法时,i - 1会自动转型为int,也就是说,传给remove方法的参数是一个int值
接下来呢?int值会被自动包装成Integer还是Short?对Java的泛型和Auto-Boxing不是很了解,于是在这犯迷糊了,只好将目前的思路草草写了几笔,交卷……
作为一名后知后觉的Java爱好者,自然不能放过这么有意思的题目。如是回来之后,上机亲自试验,输入试题程序,出来的结果果然是10(嗯,没骗我……)。然后验证自己的猜测:将Set<Short>改为Set<Integer>,输出结果……1!
看来我还是有一定的嗅觉的……
接下来就是探索原因了
首先验证一下i - 1得到的结果会不会有错:-1,0,1,……8。嗯,是对的
然后验证一下每次remove之后有没有真的remove掉指定的值……发现没有。
苦思……
经一位精研C++的同学提醒:是不是因为存的是short,但删的是int,所以不能删?
试验一下:
short
temp
=
1
;
Short s
=
new
Short(temp);
//
不能是new Short(1),否则编译出错
Integer i
=
new
Integer(
1
);
System.out.println(s.equals(i));
输出结果……false!看来终于找到真正的原因了。
查看一下Short.equals()方法的源代码:
public
boolean
equals(Object obj)
{
if
(obj
instanceof
Short)
{
return
value
==
((Short)obj).shortValue();
}
return
false
;
}
ft……居然不是同一类型的就无视……这跟胸怀广阔的集合框架背道而驰啊……当然,这是我的错
目前可以大致推断:因为set中存入的是值为0~9的Short型对象,而每次删除是是要求删除值为-1~8的Integer型对象,但值相同的Short与Integer看来并不“相等”,所以无法删除。
那就看一下HashSet的remove方法究竟干了些什么
public
boolean
remove(Object o)
{
return
map.remove(o)
==
PRESENT;
}
public
V remove(Object key)
{
Entry
<
K,V
>
e
=
removeEntryForKey(key);
return
(e
==
null
?
null
: e.value);
}
终于到主菜了……
/** */
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
* for this key.
*/
final
Entry
<
K,V
>
removeEntryForKey(Object key)
{
int
hash
=
(key
==
null
)
?
0
: hash(key.hashCode());
int
i
=
indexFor(hash, table.length);
Entry
<
K,V
>
prev
=
table[i];
Entry
<
K,V
>
e
=
prev;
while
(e
!=
null
)
{
Entry
<
K,V
>
next
=
e.next;
Object k;
if
(e.hash
==
hash
&&
((k
=
e.key)
==
key
||
(key
!=
null
&&
key.equals(k))))
{
modCount
++
;
size
--
;
if
(prev
==
e)
table[i]
=
next;
else
prev.next
=
next;
e.recordRemoval(
this
);
return
e;
}
prev
=
e;
e
=
next;
}
return
e;
}
代码就不用解释了,大家都看得懂。
HashSet里面删除一个元素时,首先要根据传进来对象的hash值从hash table中找到对应的“Entry”,当然,难免会有碰撞的情况,这时需要遍历一下来找到真正需要删除的对象。一直到这一步,Short和Integer的差异还没有体现出来,因为它们返回的hash值是相同的,但当执行key.equals(k)的时候,就“不相等”了,因此找不到要删除的元素,删除失败
小小的一道题,囊括了Java方方面面的细节,果然语言这个东西博大精深啊,有时候你以为自己很明白了,但随便揪出一个细节来就足以打到你……
大家还是好好学习,天天向上吧
posted on 2008-11-02 19:52
This is Wing
阅读(639)
评论(3)
编辑
收藏
所属分类:
Java基础
评论:
#
re: 一道小而精巧的笔试题——Set、equals、类型转换……
sclsch
Posted @ 2008-11-04 09:23
讲得不错啊。学习了。
回复
更多评论
#
re: 一道小而精巧的笔试题——Set、equals、类型转换……
sclsch
Posted @ 2008-11-04 09:47
请讲讲
removeEntryForKey
这段代码吧,
我是新手,看不懂。
回复
更多评论
#
re: 一道小而精巧的笔试题——Set、equals、类型转换……
This is Wing
Posted @ 2008-11-04 16:02
@sclsch
其实我建议你先去回顾一下数据结构中的哈希表,比如怎么存储,怎么解决碰撞,怎么查找……这些都是很基础的东西,很多地方都要用到。相信当你搞懂哈希表之后,自然也就知道上面的代码是在做什么了
回复
更多评论
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
Chat2DB
C++博客
博问
管理
相关文章:
垃圾回收(转载)
一道小而精巧的笔试题——Set、equals、类型转换……
对象的序列化和反序列化(转载+原创)
java线程基本知识小结
静态Proxy与动态Proxy用法浅析
The Collections Framework (摘要)- Part 4
The Collections Framework (摘要)- Part 3
The Collections Framework (摘要)- Part 2
The Collections Framework (摘要)- Part 1
Copyright © This is Wing
Powered by:
博客园
模板提供:
沪江博客