哈希表结构存储元素:
每个对象都有自己的哈希值,哈希表数据结构就是根据这个值进行存储的,但是由于这个值是系统确定且无序的,
因此存进去的时候数据就是无序的,往外取得时候是按照hash值从小到大取,因此存取不一定是一致的。
注意:如果两个对象的hash值一样(通常是不可能的,但是通过复写hashCode方法来自定义hash值),那么还
要再比较两个对象是否相等,调用equals方法。如果不相等,那么就在该hash值下再顺延出一片空间存储第二
个对象,如果相等,那么第二个就不存入集合了。
特点:
1.无序:
每个对象的hash值是无法确定的,因此当我们将对象存入HashSet中时,我们无法知道它被存入hash表的哪个位置,但是当我们遍历hash表时,
是按照hash值从小到大遍历的,因此元素在被存入和取出时的顺序不一定是一致的。
2.不重复:
hash表是如何保证数据不重复的呢?主要依赖于两个方法hashCode和equals,当我们将一个元素添加进hash表时,在HashSet底层的处理流程
如下:
(1)通过对象的hashCode方法计算得到hash值
(2)将此值于表中的元素的hash值进行比较
(3)如果找不到相同的,那么就直接按照hash值存入hash表
(4)如果找到相同的,那么调用该对象的equals方法与hash值一样的那个元素进行比较
(5)如果不同,则在此hash值代表的空间下顺延一片空间存储自身对象
(6)如果相同,则视为重复元素,不存储
在我们使用contains,remove等方法时,由于这些方法中都包含了在集合中查找是否有相同对象的操作,因此就要进行两个元素是否相等的比较:
对于ArrayList:是否相等只依赖于对象的equals方法。
对于HashSet:是否相等依赖于hashCode和equals方法。
原因:底层的数据结构的不同,依赖于hashCode是hash表的特点。
例子:
我们想将人对象存入HashSet中,相达到不重复(假定名字和年龄一样为重复元素)的效果,如果直接添加,打印,那么是会输出我们看来的
重复元素的,因为每个对象的hash值都是不同的,因此我们需要复写hashCode方法,希望姓名和年龄一样的对象的hashCode也是一样的,
同时也要复写equals方法,否则是否相同元素就是看地址了。代码如下:
- import java.util.*;
- class Person
- {
- private String name;
- private int age;
- Person(String name,int age)
- {
- this.name=name;this.age=age;
- }
- public String getName()
- {return name;}
- public int getAge()
- {return age;}
- public boolean equals(Object obj)
- {
- if(!(obj instanceof Person))
- return false;
- Person p=(Person)obj;
- System.out.println(this.name+".....equals run....."+p.getName());
- return this.name==p.getName()&&this.age==p.getAge();
- }
- public int hashCode()
- {
- return name.hashCode()+age*13;
- }
- }
- class HashSetTest
- {
- public static void main(String[] args)
- {
- HashSet hs=new HashSet();
- hs.add(new Person("helong1",22));
- hs.add(new Person("helong2",23));
- hs.add(new Person("helong3",24));
- hs.add(new Person("helong1",22));
- hs.add(new Person("helong2",23));
- hs.add(new Person("helong3",24));
-
- for(Iterator it=hs.iterator();it.hasNext();)
- {
- Person p=(Person)it.next();
- sop(p.hashCode()+"....."+p.getName()+"...."+p.getAge());
- }
- }
- private static void sop(Object obj)
- {System.out.println(obj);}
- }
复制代码
|
|