1.先清除HashSet是怎么存储数据的.首先,往set里面添加数据的时候,会自动调用hashcode()方法,这个方法就是拿现在对象的hash码和set集合中其他数据的hash码比较(实际是跟哈希表中的记录的 hashcode比较 ) 如果都不相同,就直接添加数据.hash码是根据地址计算的,hash码不同,则地址肯定不同,则肯定不是一个对象.hashcode()就是用来筛选一些地址相同的数据.但是比较的hash码如果有相同的,则会去调用equals(),用来比较具体的属性值,看相同不相同.属性值相同,则不添加.不相同就会添加.
2.如果set中存放的是int类型等一些基本类型 和 String类型的 是不允许内容重复的,即相同的内容如果存放在set里面是不允许的,这是因为这些类型的内容相同的话,他们的地址也相同.
- 如果想要实现 HashSet中 属性值相同就认为是同一个对象, 不添加到集合中,则需要重写hashcode和equals方法.因为原本hashcode()就是根据计算地址来进行比较的,所以重写的hashcode()不要计算地址,而是和属性值有关的来进行计算,如果属性值相同,则不会加入到集合中.
4.下面5中hashcode()是自己写的,也可以快捷方式自动生成.如
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + height;
return result;
}
在这里有一个prime.这是为了把数的范围扩大,为了避免属性值不同,但是返回的result相同的情况,这种情况下就会调用equals方法.而实际上属性值不同时,如果把数的范围扩大,就不大有可能出现result相同的情况.(自行体会)
3.person类
package com.qf.demo3;
public class Person {
private int age;
private int height;
public Person(int age, int height) {
super();
this.age = age;
this.height = height;
}
public Person() {
super();
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [age=" + age + ", height=" + height + "]";
}
// 是根据内存地址 经过一定的运算得到的
//重写hashcode 也行者 得到属性值的hashcode
@Override
public int hashCode() {
//System.out.println("hashcode");
int result = 0;
result += age;// int hashcode值就是自己本身
result+= height;
return result;
// name sex height
// 1 2 3 4
// 2 1 3 4
/**
* 和 如果不一样 属性一定不一样
*
* 和 一样 属性值 不一定一样
* 只有 hashcode 值 相同的时候 才去调用equals方法 来确定 是否真的各个属性值都一样
*
*/
}
// 重写以后就是比较的属性值
@Override
public boolean equals(Object obj) {
System.out.println("equals");
if(obj == this){
return true;
}
if(obj == null){
return false;
}
if (obj instanceof Person) {
Person person = (Person) obj;
if(this.age == person.age && this.height == person.height){
return true;
}
}
return false;
}
}
main:
package com.qf.demo3;
import java.util.HashSet;
/**
* Set 无序 不允许重复的
*
* @author Administrator
*HashSet : 无序 是展示顺序与存入顺序不同\
*哈希表: 存储很多的hashcode
*
* 1 存储数据的时候 先 得到 这个数据的hashcode , 拿这个hashcode 跟 哈希表中 的 记录的 hashcode比较 , 没有相同的
* 就认为 是不同的对象, 存入到集合
*
* 如果相同 3+3 = 6
* 2*3 = 6
*
*
* 再去 调用 equals方法 比较每一个属性值
*
*也没有从小到大排序
*/
public class Test {
public static void main(String[] args) {
HashSet<String> set = new HashSet<>();
set.add("d");
set.add("a");
set.add("w");
set.add("w");// 不允许 重复
System.out.println(set);
HashSet<Integer> set2 = new HashSet<>();
set2.add(8);
set2.add(10);
set2.add(1);
set2.add(8);
System.out.println(set2);
// 每add一次 就会调用hashcode, 用 要添加的 数据的hash值 跟哈希表中 存储的多个哈希值对比
// 如果不相同 则一定不是同一个对象 , 就添加到set集合中
HashSet<Person> set3 = new HashSet<>();
set3.add(new Person(7,1));
set3.add(new Person(2,3));
set3.add(new Person(2,3));
set3.add(new Person(3,2));// 只要内容相同 就认为是同一个对象
System.out.println(set3);
}
}
总结:
-
需求
-
HashSet中 属性值相同就认为是同一个对象, 不添加到集合中
-
1 创建类, 重写 hashcode 和 equals
hashcode 各个属性的hashcode值加和
equals 每个属性值比较是否相同 -
2 添加数据时 每添加一个数据就会 调用一次hashcode
-
3 判断hashcode值 是否已经存在 ,如果不存在 直接将数据加到set集合中 ,不调用equals
-
4 如果 hashcode值已经存在, 调用equals 方法
-
如果eqeuals 返回 false 则认为是不同对象 添加到 set 中
-
如果 equals 返回 true 真正的是 每个属性值 都相同 就认为是同一个对象 不添加到set 中
网友评论