Set总述
set存储的数据是唯一性的,是通过存储的对象的两个方法进行唯一性判断的hashCode( )和equals(),在调用集合的add(E e)方法时,会进行判断,通过e.hashCode( )获取要添加对象的hash值,和集合里面的对象进行判断,如果hash值不一样,则会存储。如果一样,则会调用equals()方法,和集合中hash值一样的对象进行判断,如果有一个equals返回true,则判定一样,直到所有大的hash值一样的数据,通过equals方法都为false,才会存储。(set的存储结构是hash表,hash值一样的时候,往存储(类似数据结构中,解决hash冲突的第二种方式))。
代码分析
- 建立一个hashSet集合对象,往里面存储User对象,分析执行步骤。
- set调用add(e)方法,
- 获取通过e.hashCode()获取对象的hash值。
- 将判断集合中,是否存在相同的hash值,没有则存储
- 集合中存在相同的hash值对象,则取出这些hash值和e的相同的对象
- 遍历这些相同hash值相同的对象,通过调用e.equals()判断是否一样,不一样,则保存。
案例分析
- 创建user对象,重写equas(User u),和hashCode(),这里hashCode返回数据是一样的,让存储的时候都进行判断。
package day14_list.setDemo;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
/**
* 重写equal方法,让hash值一样是,唯一性判断,按自己<br>
* 需求来,如果不更改,则是按照对象地址值进行判断。
*/
public boolean equals(Object obj) {
if (!(obj instanceof User))
return false;
User u = (User) obj;
System.out.println(this.name + "-----" + u.getName());
return (u.getName().equals(name));
}
@Override
/**
* 重写hashcode(),让返回值一样,方便进行测试,这样每加入一个元素<br>
* hash值是一样的,则会进行equals判断。
*/
public int hashCode() {
return 60;// 实际开发可用 name.hashCode(),减少hash冲突,提高效率
}
}
- set调用add方法,进行存储
package day14_list.setDemo;
/**
*
* 类名:set的判断元素重复是根据hash值,要判断,需要自定义
* 生成的hash值
*
* hashSet 保证元素对象的唯一性:
* 1-通过复写hashSet方法,改变要存储对象的hashcode值,
* 先判断hash值是否一样
* 2-hash值一样时,通过equal方法判断;
*
* @author mahao
* @date 2018年6月25日
* Description:
*/
public class SetDemo {
@Test
public void demo2() {
Set<User> set =new HashSet<User>();
User u1 = new User("user1");
set.add(u1);
User u2 = new User("user2");
set.add(u2);
User u3 = new User("user3");
set.add(u3);
User u4 = new User("user2");
set.add(u2);
for(User u: set){
System.out.println(u.getName());
}
}
}
-
将判断集合中,是否存在相同的hash值,没有则存储(jdk中源码)
-
集合中存在相同的hash值对象,则取出这些hash值和e的相同的对象
6. 上图中可以看到是通过e.equals(k),进行数据比较。
执行结果为