黑马程序员技术交流社区
标题:
HashSet存储重复元素的问题
[打印本页]
作者:
陈冲
时间:
2012-9-15 21:29
标题:
HashSet存储重复元素的问题
本帖最后由 陈冲 于 2012-9-15 22:03 编辑
今天复习张孝祥老师的视频,在看到反射那部分的时候,有个HashSet的应用,在修改了对象的值以后,该元素无法移除。
我就在想是否能添加一个对象,这个对象的值与上面修改后的对象的值相同,没想到真的成功了。
有没有知道这是为什么的?
以下是代码:
public class ReflectPoint {
private Date birthday=new Date();
private int x;
public int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "x:"+x+" y:"+y;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
复制代码
import java.util.Collection;
import java.util.HashSet;
public class ReflectTest {
public static void main(String[] args) {
Collection collections=new HashSet();
ReflectPoint pt1=new ReflectPoint(3, 3);
ReflectPoint pt2=new ReflectPoint(5, 5);
ReflectPoint pt3=new ReflectPoint(3, 3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
System.out.println(collections);
pt1.y=7;
collections.remove(pt1);
collections.add(new ReflectPoint(3,7));//上面的pt1修改为了x=3,y=7,这里再次添加3,7
System.out.println(collections.size());
System.out.println(collections);
}
}
复制代码
输出结果是 [x:3 y:7, x:3 y:7, x:5 y:5]
作者:
张 涛
时间:
2012-9-15 21:45
比如:
你new了一个某类型的对象c,内容是x-3,y-6;
然后你把这个对象c添加到了map中,map中有一个某类型的对象,内容是x-3,y-6。
然后你修改了c,变为了x-4,y-6;
然后你删c,在map中找不到c,因为找的时候,是按照equals方法和hashmap方法比较的。第一次添加的某类型对象的内容是x-3,y-6,和现在c对象的x-4,y-6不匹配。所以找不到。
然后你添加一个x-4,y-6,这个按照equals方法和hashcode方法,发现在map中没有和他相同的,当然可以添加了。
作者:
佟亚鹏
时间:
2012-9-15 21:52
呵呵,张老师的高新技术视频我看三遍了,每次都有新的收获。关于这个,请看代码中我加的注释
import java.util.Collection;
import java.util.HashSet;
public class ReflectTest {
public static void main(String[] args) {
Collection collections=new HashSet();
ReflectPoint pt1=new ReflectPoint(3, 3);
ReflectPoint pt2=new ReflectPoint(5, 5);
ReflectPoint pt3=new ReflectPoint(3, 3);//这个加不进去了,
<span style="color: rgb(51, 102, 153); font-family: Monaco, Consolas, 'Lucida Console', 'Courier New', serif; font-size: 12px; line-height: 21.600000381469727px; background-color: rgb(255, 255, 255); ">ReflectPoint </span> 的hashcode是根据,x、y算出来的
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);//加不进去,重复了
collections.add(pt1);//加不进去,重复了
System.out.println(collections.size());//结果是2
System.out.println(collections);
//目前集合中的元素是 <span style="background-color: rgb(255, 255, 255); "> [x:3 y:3, x:5 y:5]</span>
pt1.y=7;//修改了pt1的y值,hashcode变掉了,由于移除对象需要判断它的hashcode,此时集合中不存在这个被修改的hashcode值,集合保存的hashcode仍然是修改前的hashcode,所以这个对象移除不了
collections.remove(pt1);
//虽然集合中已经有了个x=3,y=7的pt1对象,但是集合中它所在的hash区域,仍然是根据x=3,y=3时计算出的hashcode值确定的,而加入的对象的hashcode值是根据x=3,y=7计算出来的,所以在集合中与pt1的hashcode值不同,则认为这个对象在集合中不存在所以存了进来
复制代码
过程都写在了注释中了,楼主好好体会下,不是看x、y值,重点看hashcode的值,对象放在集合中的位置是根据加入集合时的hashcode值确定的,加入新的对象时,根据hashcode值判断下相应区域是否有这个对象,明白这些,就能理解了
作者:
程振
时间:
2012-9-15 22:01
这个问题你需要查看JDK的源码
首先看HashSet的Add方法,因为HashSet是利用现有的HashMap来实现的,即把HaspMap的value固定为PRESENT 对象:private static final Object PRESENT = new Object();
这个你要理解
然后你调用HashSet的add方法时,执行下面的代码
public boolean add(E e) {
return map.put(e, PRESENT)==null; //调用HashMap的put方法
}
复制代码
下面需要看看HashMap的put方法
看里面的关键两句
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode()); //
int i = indexFor(hash, table.length); // 确定key在hash表中的位置
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
复制代码
所以当你调用HashSet的add方法时,value的位置已经确定了,之后你修改的对象对HashSet也产生影响,因为它们都指向同一个内存地址。
简单的说就是插入时根据value的hashcode,看看对应的表的位置有没有占用,以此来判断是否添加成功。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2