您的位置:首页 > 编程语言 > Java开发

HashSet不重复存储元素的执行过程

2015-10-04 21:28 701 查看
      十一嘛,该干点啥呢?既然没啥事儿可干,那就继续看看代码吧。好的,那就开始技术。

       在前几篇博客中写了关于ArrayList的一些知识,现在就学一个Set集合的东西,Set集合:元素不可重复,是无序的

其中在Set接口中的方法和Collection一致,HashSet和TreeSet是常用子类。这次我们主要用到HashSet!

HashSet:内部数据结构是Hash表,底层存储通过算法实现,根据元素自身的特点,确实其存放的位置。是不同步的。

其中最大特点就是不重复,和无法按输入顺序输出。看一个代码的例子:

public class HashSetDemo {

public static void main(String[] args) {

HashSet hs = new HashSet();

hs.add("linweieran");
hs.add("linweieran");
hs.add("haha48");
hs.add("heihei");

Iterator it=hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}

结果证明没有按输入顺序输出字符串,同时也是不可重复。
这就用到了hash算法中的hasCode()  and equals()方法。但是当存储自定义对象的时候就出现了一定的“重复”。

public static void main(String[] args) {

HashSet hs=new HashSet();

hs.add(new Person("linweieran",24));
hs.add(new Person("linweieran1",23));
hs.add(new Person("linweieran2",22));
hs.add(new Person("linweieran3",25));
hs.add(new Person("linweieran",24));

Iterator it =hs.iterator();
while(it.hasNext()){
Person p=(Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}其中Person类,就是前一个博文里用到的Person类。


可以看出元素出现了重复。分析原因,这是因为在HashSet集合中对每一个新对象都hash一个新值。那么HashSet是如何hash、如何进行不重复存储的呢?

      hash运算估计学过计算机的都知道这个,hash当在影射位置已有对象是有链表也有后移的存储方式,这个在这里就说了,整个 存储机制怎么运行呢?

      (1)首先向集合中存储元素或者对象的时候,通过hashCode()函数计算出hash值;

      (2)再通过equals()函数判断相同的是否存在,如果存在就不存,否则存入,在Java中的底层代码HashCode()代码如下:

public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}

equals代码如下:
public boolean equals(Object o) {
if (o == this)
return true;

if (!(o instanceof Set))
return false;
Collection c = (Collection) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}但这这是遇到String类型时候会这样做,但遇到先前提到的Person类的时候,有这样的功能,必须复写hashCode 和equals方法,具体代码如下:
public class Person {

private String name;
private int age;

//alt+shift+s

public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}

@Override
public int hashCode() {

System.out.println(this+"....hashCode");
int nameNu=name.hashCode();
return nameNu+age;
}

@Override
public boolean equals(Object obj) {

if(this==obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException();//类型错误

Person p = (Person)obj;
System.out.println(this+"...equal..."+p.name);
return this.name.equals(p.name)&&this.age==p.age;
}

public String toString(){
return name+":"+age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

}对于hashCode简单的写为返回name+age;对于equals 当名字和年龄相同时,就认为是同一个人。
通过看一下执行步骤


可以看出所写的执行过程是正确的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java 集合