读书人

黑马软件工程师_集合学习之hashset学习

发布时间: 2013-04-09 16:45:09 作者: rapoo

黑马程序员_集合学习之hashset学习笔记

------- android培训、java培训、期待与您交流! ----------

在collection中,除了list派系之外,还有一个set派系

Set中元素是无序的,也就是存入和取出顺序不一定一致,而且元素不能重复。

更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1e2,并且最多包含一个 null 元素

查看set接口的功能,才发现set和collection是一致的。

在set接口下,有两个我们常用的类比较重要

HashSet:它的底层数据结构式哈希表

TreeSet

什么叫做哈希表?

比如,我们定义了两个Demo对象

class Demo

{

}

Demo d1 = new Demo();

Demod2 = new Demo();

System.out.println(d1);//输出day1.Demo@150bd4d

System.out.println(d2);//输出day1.Demo@1bc4459

这是定义了一个哈希结构的集合。将上述两个对象的哈希值存入到集合中

150bd4d,1bc4459


注意,存放的顺序不是按照你存入的数据去定义的。这也就是和arraylist的区别

顺序是按照哈希值的顺序去存入的。

在我们去取的时候,是按照表里边的顺序去取。

经过我的测试,在其类中加入了

class Demo

{

publicinthashCode()

{

System.out.println("1");

return 0;

}

}

已验证是否在进入集合中时候,调用了自身的hashCode()方法。

Demo d1 = new Demo();

Demod2 = new Demo();

HashSet<Demo> hs = newHashSet<Demo>();

hs.add(d1);

hs.add(d2);

输出了

1

1

故以上得以证明确实调用了对象的hashcode方法。

切记,哈希表是按照哈希值来存储的。当哈希值一样的时候,

还有一次校验的方式。就是使用看是否是同一个对象。也就是调用对象的equals

方法。 如果equals不等的话,就会在该hashcode对应的地址顺延

如两个hashcode都为1,但是equals不同

则 1(同一地址,这里存放一个对象)------1(另一个对象),也就是


黑马软件工程师_集合学习之hashset学习笔记

如果hashcode的值不一样,那么没有必要计较equals方法了

这里突然想到了equals和==的区别,

==比较的是两个对象的内存地址是否一致。

Demo d1 = newDemo();

Demo d2 = new Demo();

则d1==d2为false

Demo d1 = newDemo();

Demo d2 = d1;

则d1==d2为true

当使用equals方法时候,如果对象实现了equals方法,则使用其自己的。

如果没有实现,则调用从object中得到的。

publicbooleanequals(Object obj){

return (this ==obj);

}

其实也就是比较的内存地址了。

也就是如果你没有实现equals方法,则==和equals得到的值一样。

其实hashset就是hash表结构的。。。

HashSet<String>hs = new HashSet<String>();

hs.add("java01");

hs.add("java02");

hs.add("java03");

hs.add("java03");

for(Strings:hs)

{

System.out.println(s);

}

java02

java03

java01

这里我们验证了不可重复和无序的规律

这里我们来说往hashSet集合中存入自定义对象。

classPersonDemo

{

privateStringname;

publicPersonDemo(String name,int age) {

super();

this.name =name;

this.age =age;

}

privateintage;

publicString getName() {

returnname;

}

publicvoidsetName(String name) {

this.name =name;

}

publicintgetAge() {

returnage;

}

publicvoidsetAge(int age) {

this.age =age;

}

publicinthashCode()

{

System.out.println("code");

returnname.hashCode()+age;

}

publicboolean equals(Objecto)

{

System.out.println(“equals”);

PersonDemo p = (PersonDemo)o;

returnname.equals(p.name)&&age==p.age;

}

}

上边我们定义了一个对象并实现了equals和hashCode(根据具体的比较形式)。

并创建

HashSet<PersonDemo>hs = new HashSet<PersonDemo>();

hs.add(newPersonDemo("dabin",11));

hs.add(newPersonDemo("dabin1",12));

hs.add(newPersonDemo("dabin2",13));

hs.add(newPersonDemo("dabin2",13));

控制台输出

hashcode

hashcode

hashcode

hashcode

equals

原理如下。

Dabin对象调用hashcode的到一个哈希吗。放到内存中

Dabin1对象调用hashcode的到一个哈希吗。与dabin比较,hashcode不同,放到内存中。

Dabin2对象调用hashcode的到一个哈希吗。与dabin1和2比较,hashcode不同,放到内存中。

当再次存入dabin2的时候,由于hashcode码一样,故调用了equals方法。

Dabin(码)

Dabin1(码)

Dabin2(码)

由于equals方法一致,所以。Dabin2没有被放入。

综上,hashset是通过hashcode和euqals保证元素的一致性。

当说完增加元素的时候,我们说一说删除和寻找元素的原理

HashSet<PersonDemo>hs = new HashSet<PersonDemo>();

hs.add(newPersonDemo("dabin",11));

hs.add(newPersonDemo("dabin1",12));

System.out.println(hs.contains(newPersonDemo("dabin1",12)));

输出为

hashcode.....dabin

hashcode.....dabin1

hashcode.....dabin1//得到了要寻找的hash值,比较后,存在一个hashcode一致的对象,则调用equals做进一步判断

equals//也一致。

True//所以发现元素包含。

Remove也是同样的比较方式。。。

但是对于arraylist来说,只是去比较equals方法,与hashcode无关。


读书人网 >编程

热点推荐