作者adrianshum (Alien)
看板java
标题Re: [J2SE] Java HashSet观念请教
时间Fri May 2 15:07:47 2008
※ 引述《Harifucks (就是要战脑残保险业务)》之铭言:
: 各位先进午安,请教一个HashSet观念:
: import java.util.*;
: class KeyMaster
: {
: public int i;
: public KeyMaster(int i) { this.i = i; }
: public boolean equals(Object o)
: {
: return i == ((KeyMaster)o).i;
: }
: public int hashCode() { return i; }
: }
: public class MapIt
: {
: public static void main(String[] args)
: {
: Set<KeyMaster> set = new HashSet<KeyMaster>();
: KeyMaster k1 = new KeyMaster(1);
: KeyMaster k2 = new KeyMaster(2);
: set.add(k1); set.add(k1);
: set.add(k2); set.add(k2);
: System.out.print(set.size() + ":");
: //k2.i = 1;
: System.out.print(set.size() + ":");
: set.remove(k1);
: System.out.print(set.size() + ":");
: set.remove(k2);
: System.out.print(set.size());
: }
: }
: 结果是2:2:1:0,没有问题;但如果我把//k2.i = 1;这行程式Enable,
: 结果会变成2:2:1:1。请问,这里面造成变化的原因是?谢谢回答!
这个问题, 你明白 hashtable 的工作原理就会了解.
但简单一句就是: 作为 hash table 的 key (HashSet 则是
值本身), 一旦加入了 hash table, 就不应该再修改其值.
java 上面的 hash table 概念大概就是一个 array, 当你加入 data
就以其 hash 值来决定要把 value 放在 array 的哪一格, array 的每
格则是一个 linked list. 如果有同 hash但不同值 (equals return false)
就加在该格的 linked list.
拿你的情况来说,
KeyMaster k1 = new KeyMaster(1);
KeyMaster k2 = new KeyMaster(2);
set.add(k1); ... 1
set.add(k2); ... 2
k2.i = 1; ... 3
set.remove(k1); ... 4
set.remove(k2); ... 5
1) 的时候, k1 的 hash 值是 1, 放在 hash set 里的 array
的第一格, 2) 则把 k2 放第二格
3) 你把 k2 指着的 object 的值改成 1. 这也做成了, set
里的 array 的第二格指着的是一个 值是 1 的 obj.
3) 想 remove k1, 做的是, 拿传进来的 obj, 取 hash 得 1,
因为拿到是 1, 所以去 hash set 的 array 第一格检查, 里面
有一个 obj (原先加进的 k1), 两者作 equals, 发觉相等, 所以
就把该 obj 从 array 移走. 这时 array 里只剩第二格指着一个
值为 1 的 obj.
4) remove k2, 这时 k2 的值是 1, 取 hash 得 1, 去 array 第一格
检查发觉没有东西, 所以就直接离开. 所以最後 set 还剩 1 个
element
了了吗?
alien
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 202.155.236.82
※ 编辑: adrianshum 来自: 202.155.236.82 (05/02 15:08)
1F:推 Harifucks:很清楚,谢谢y 05/02 17:15