聊城做网站费用,设计图片制作软件免费,云南做公司网站多少钱,wordpress 更改页面排版前言部分
SetT 去重相信大家一定不陌生#xff0c;尤其是在 SetString、SetInteger 等等#xff0c;但是在使用 Set实体 #xff0c;在不重写 equals()、hashCode() 方法情况下#xff0c;直接使用貌似并不能生效。
所以想要 Set实体…前言部分
SetT 去重相信大家一定不陌生尤其是在 SetString、SetInteger 等等但是在使用 Set实体 在不重写 equals()、hashCode() 方法情况下直接使用貌似并不能生效。
所以想要 Set实体 实现去重核心部分在实体中重写 equals()、hashCode() 方法。
如下以 User 实体为例进行测试。
代码部分
测试代码
public static void main(String[] args) {SetUser userSet new HashSetUser(){{add(new User(张三,10));add(new User(张三,20));add(new User(张三,10));}};userSet.forEach(user - {System.out.println(String.format(name: %s, age%s,user.getName(),user.getAge()));});
}打印结果
name: 张三, age20
name: 张三, age10实体对象(User.java) 重写了 equals()、hashCodd() 方法。
public class User {public User(String name, Integer age){this.name name;this.age age;}/** 姓名 **/private String name;/** 年龄 **/private Integer age;省略get、set方法.../*** 重写equals方法如果对象类型是User,先比较hashcode一致的场合再比较每个属性的值*/Overridepublic boolean equals(Object obj) {System.out.println(调用equals方法当前的hashCode为hashCode());/** 对象是 null 直接返回 false **/if (obj null) {return false;}/** 对象是当前对象直接返回 true **/if (this obj) {return true;}/** 判断对象类型是否是User **/if (obj instanceof User) {User vo (User) obj;/** 比较每个属性的值一致时才返回true **//** 有几个对象就要比较几个属性 **/if (vo.name.equals(this.name) vo.age.equals(this.age)) {return true;}}return false;}/*** 重写hashcode方法返回的hashCode一样才再去比较每个属性的值*/Overridepublic int hashCode() {return this.getName().hashCode() * this.getAge().hashCode();}}解释部分
为什么 SetString、SetInteger 就可以直接实现去重而 Set实体 就不可以反而要重写 equals()、hashCode() 方法才能实现更甚者是只重写 equals() 方法而不重写 hashCode() 方法都没法完成去重~
大家对这个问题有过疑惑吗
1、HashSet 添加数据过程
HashSet 的底层实现相信大家都清楚是 HashMap 吧我们在 add() 数据时其实一层层找最终是调的 HashMap 的 put() 方法如下是 HashSet 的 add() 方法其中 map 为 HashMap。 我们再点一层找到 HashMap 的 put() 方法 如上图所示通过 putVal() 方法我们大致有了个概念了判断是否为旧值就是对 hash 值、key 值进行比较。
hash 值比较自然调用的事 hashCode() 方法而 key 值的比较实用的是 equals() 方法。
了解到这基本就可以看出 hashCode() 、equals() 方法对于去重的重要性了。
2、Set单属性 可以直接使用去重
那么接下来我们就可以来看看 Set单属性单属性String、Integer等为什么直接使用就可以去重了。
我们以 String 为例假设有两个字符串 a、b如下
String a 123;
String b 123;
System.out.println(a.hashCodea.hashCode());
System.out.println(b.hashCodeb.hashCode());
System.out.println(a.equals(b));打印结果如下
a.hashCode48690
b.hashCode48690
true很显然在没有重写 hashCode() 、equals() 方法时字符串 a、b 的 hashCodeequalse() 是一致的那么这两个就可以视为一个对象所以用在 Set 里面就可以直接去重。
但是为什么会一致呢
任何对象在不重写 equals()、hashcode() 的情况下使用的是 Object 对象的 equals() 方法和 hashcode() 方法而重点就是默认的 equals() 方法判断的是两个对象的引用指向的是不是同一个对象而 hashcode 也是根据对象地址生成一个整数数值
显然字符串 a、b 这两个条件都满足所以对于 Set 来说就是一个对象的概念。
3、Set实体 去重
但是换到对于实体对象就行不通了我们再来套 Object 的 equals()、hashCode() 方法。
当我们 new User() 对象时两个对象的地址引用肯定是不同的其次 hashcode 是根据对象地址生成的这样显然也不同所以对于 Set 来说那么去重就行不通。
因此想要让 Set实体 实现去重效果那么就需要重写 equals() 、hashCode() 方法。
只有两个对象的 hashCode() 方法的值一致且 equalse() 方法返回 true那么这对于 Set实体 来说就可以看做一个对象 如果两者只满足一个是不可以的只重写一个举个例子
equales()重写hashCode()不重写
Override
public boolean equals(Object obj) {return true;
}//Override
//public int hashCode() {
// return this.getName().hashCode() * this.getAge().hashCode();
//}执行代码
SetUser userSet new HashSetUser(){{add(new User(张三,10));add(new User(张三,20));add(new User(张三,10));
}};userSet.forEach(user - {System.out.println(String.format(name: %s, age%s,user.getName(),user.getAge()));
});打印内容
name: 张三, age10
name: 张三, age10equales()不重写hashCode()重写
//Override
//public boolean equals(Object obj) {
// return true;
//}Override
public int hashCode() {return this.getName().hashCode() * this.getAge().hashCode();
}执行代码打印内容如上
name: 张三, age10
name: 张三, age10总结
总之要想保证 Set实体 实现去重就需要两个实体 “一致”这里的一致是只需要满足如下两个条件
重写 hashCode() 方法确保两者 hashcode 一致比如使用属性相乘或者相加。重写 equals() 方法相同对象、属性值相同对象皆为相等。
通过上面这些例子也能看出重写 equals 方法就必须重写 hashCode 的重要性因为只重写 equals() 不一定能满足预期相等的效果。
如下是阿里巴巴开发手册关于 hashCode 和 equals 的处理规则 希望这篇文章对你有所帮助。博客园持续更新欢迎关注。 博客园https://www.cnblogs.com/niceyoo