26_ArrayList_HashSet的比较及Hashcode分析
实体类:
package com.itcast.day1; public class ReflectPoint {
private int x;
public int y; public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ReflectPoint other = (ReflectPoint) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
} }
测试类:
package com.itcast.day1; import java.util.Collection;
import java.util.HashSet; public class ReflectTest2 {
public static void main(String[] args) {
// Collection collections = new ArrayList();
Collection collections = new HashSet();
ReflectPoint pt1=new ReflectPoint(3,3);
ReflectPoint pt2=new ReflectPoint(5,5);
ReflectPoint pt3=new ReflectPoint(3,3); //ReflectPoint类重写了hashCode方法---算法依据x,y。
collections.add(pt1);//放入
collections.add(pt2);//放入
collections.add(pt3);//hashCode比较后,和pt1在同一区域;比较equals发现相同,舍弃pt3这个引用
collections.add(pt1);//hashCode比较后,和pt1在同一区域;比较equals发现相同,舍弃
System.out.println("修改pt2.y 前, size= "+collections.size());//2 最终放入collections 了2个元素 pt2.y=4;//修改参与进行hashCode运算的 y值,则pt2此时的hashCode和上面放入collections时的hashCode是不相等的。
//这将导致Java系统无法在collections中检索到。 collections.remove(pt2);//检索不到这个修改后的pt2存储区域,自然就删掉pt2失败
System.out.println("修改pt2.y 后, size= "+collections.size());//2 所以 System.out.println("BB".hashCode()=="Aa".hashCode());//true 即:equals不相等,hashCode相等
} /**
* 在hash集合中,放入元素前,会先计算元素的hashCode,
* 然后根据这个hashCode来决定存放在哪个区域。
*
* 如果想查找一个集合中是否包含有某个对象,大概的程序代码怎么写呢?你通常是
*逐一去除每个元素与要查找的对象进行比较,当发现某个元素要与查找的对象进行equals
*方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则,返回否定的信息。
*如果一个集合中有很多个元素,譬如有一万个元素,并且没有包含要查找的对象时,
*则意味着你的程序需要从该集合中取出一万个元素进行逐一的比较才能得出结论。
* 有人发明了一种哈希算法来提高冲击和中查找元素的效率,这种方式将集合分为若干
*个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储
*区域,每个对象可以计算出一个哈希码,可以将哈希码分组,每组分别对应某个存储区域,
*根据一个对象的哈希码就可以确定该对象应该存储的哪个区域。
*
*
* HashSet就是采用哈希算法存取对象的集合,它内部采用对某个数字N进行取余的方式
*对哈希码进行分组和划分对象的存储区域。Object类中定义一个hashCode()方法来返回每个Java
*对象的哈希码,当从HashSet集合中查找某个对象时,Java系统首先调用对象的hashCode()方法
*获得该对象的哈希码,然后根据哈希码找到相应的存储区域,最后取出该存储区域内的每个元素与
*该对象进行equals方法比较,这样不用遍历集合中的所有元素就可以得到结论。可见,HashSet集合具有很好的对象
*检索性能,但是,HashSet集合存储对象的效率相对较低些,因为向HashSet集合中添加一个对象时,
*要先计算出对象的哈希码和根据这个哈希码耵对象在集合中的存储位置。
*
* 为了保证一个类的实例对象能够在HashSet正常存储,要求这个类的两个实例对象用equals()
*方法比较的结果相等时,他们的哈希码也必须相等。也就是说,如果obj1.equals(boj2)的结果为true,
*那么以下表达式的结果也要为true。 obj1.hashCode()==obj2.hashCode()
*
* 如果一个类的hashCode方法没有遵循上述要求,那么,当这个类的两个实例对象用equals()方法
*比较的结果相等时,它们本来应该无法被同事存储进Set集合中,但是,如果将他们存储进HashSet
*集合中时,由于它们的hashCode()方法的返回值不同,第二个对象首先按照哈希码计算可能被放进与
*第一个对象不同的区域中,这样,它就不可能与第一个对象进行equals方法比较了,这样可能被存储进
*HashSet集合中了。Object类中的hashCode()方法不能满足对象被列入到HashSet中的要求,因为它的返回值
*都是通过对象的内存地址推算出来的,同一个对象在程序运行期间的任何时候返回的哈希值都是始终不变的,所以,
*只要是两个不同的实例对象,即使它们equals方法比较结果相等,它们默认的hashCode方法的返回值是不同的。
*
*上面代码ArrayList集合改为HashSet集合就可以看到这种错误的结果了,修改后的代码:
*
*import java.util.HashSet;
*class Ch15_Demo5{
* public static void main(String[] args){
* HashSet users=new HashSet();
*
* users.add(new User("张三",28));
* users.add(new User("李四",28));
* users.add(new User("王五",28));
* System.out.println(users.size());
*
* users.add(new User("张三",28));
* System.out.println(users.size());
*}
*
*}
*
* 只有类的实例对象要给采用哈希算法进行存储和检索时,这个类才需要按照要求覆盖hashCode方法。即使程序
*可能暂时不会用到当前类的hashCode方法,但是为它提供一个hashCode方法也不会有什么不好,没准以后什么时候又
*用到这个方法了,所以通常要求hashCode方法和equals方法一并被同时覆盖。
*
*提示:
* (1)通常来说,一个类的两个实例对象用equals()方法比较的结果相等时,它们的哈希码也必须相等,但反之则不成立,
* 即equals方法比较结果不相等的对象可以有相同的哈希码,或者说哈希码相同的两个对象的equals方法比较的结果可以
* 不等,例如,字符串"BB"和"Aa"的equals方法比较结果可以不相等,但是它们的hashCode方法返回值却相等。
*
* (2)当一个对象被存储进HashSet集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后
* 的哈希值与最初存储进HashSet集合中的哈希值就不同了,在这种情况下,即使在contains方法使用该对象当前应用作为参数去
* HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。
*
*
*
*
*/
}
26_ArrayList_HashSet的比较及Hashcode分析的更多相关文章
- ArrayList_HashSet的比较及Hashcode分析
ArrayList_HashSet的比较及Hashcode分析 hashCode()方法的作用 public static void main(String[] args) { Collectio ...
- equals与hashcode分析
我们经常在面经中看到这样的问题,为什么重写equals方法就一定要重写hashcode方法.本文就是分析这个问题. <!--more--> 在阿里巴巴java开发手册中就给出了这样的规则. ...
- String的hashCode分析
/** * Returns a hash code for this string. The hash code for a * {@code String} object is computed a ...
- == 和 equals,equals 与 hashcode,HashSet 和 HashMap,HashMap 和 Hashtable
一:== 和 equals == 比较引用的地址equals 比较引用的内容 (Object 类本身除外) String obj1 = new String("xyz"); Str ...
- java集合框架之HashCode
参考http://how2j.cn/k/collection/collection-hashcode/371.html List查找的低效率 假设在List中存放着无重复名称,没有顺序的2000000 ...
- java高新技术-反射
一.反射的基石->Class类 定义一个类使用 class 有一个类叫Class Java程序中的各个Java类属于同一类事务,描述这类事物的Java类名就是Class. Person类代表人, ...
- Java高新技术 反射机制
Java高新技术 反射机制 知识概要: (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...
- SpringMvc RequestMappingHandlerMapping
RequestMappingHandlerMapping是SpringMvc中一个比较核心的类,查看下它的类结构图: InitializingBean是个很神奇的接口,在Spring每个容器的bean ...
- java中的==、equals()、hashCode()源码分析(转载)
在java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际的编程总结一下. 1. == java中的==是比较两个对象在JVM中的地址.比较好理解.看下面的代码: ...
随机推荐
- sql server 备份与恢复系列八 系统数据库备份与恢复分析
一.概述 在前面讲过"sql server 备份与恢复系列"都是集中在用户数据库上.sql server还维护着一组系统数据库,这些系统数据库对于服务器实例的运行至关重要.在每次进 ...
- Mac 远程连接 Windows
推荐使用微软官方发布的 Microsoft Remote Desktop,免费.流畅. 详见:https://docs.microsoft.com/en-us/windows-server/remot ...
- RocketMQ系列实战
RocketMQ实战(一)RocketMQ实战(二)RocketMQ实战(三):分布式事务RocketMQ实战(四)
- 自己动手实现java数据结构(六)二叉搜索树
1.二叉搜索树介绍 前面我们已经介绍过了向量和链表.有序向量可以以二分查找的方式高效的查找特定元素,而缺点是插入删除的效率较低(需要整体移动内部元素):链表的优点在于插入,删除元素时效率较高,但由于不 ...
- vscode使用汇总——常用插件、常用配置、常用快捷键
一.代码提示快捷键设置:(keybindings.json) [ { "key": "ctrl+j", "command": "- ...
- Java设计模式学习记录-GoF设计模式概述
前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...
- Redis持久化存储与复制功能简述
一.分布式系统基础理论 分布式系统的两个基础理论: 1.CAP理论 如图: Consistency(强一致性):数据一致更新,所有数据变动都是同步的.Availability(可用性):好的响应性能. ...
- pip更新到18版本后使用pycharm更新问题:module 'pip' has no attribute 'main'
今天升级pip到18.0版本后更新模块时出现错误 分析报错信息可知,问题出在packaging_tool.py文件的213行和109行,找到具体的代码,如下 # 109行函数 def do_insta ...
- U盘基本处理,U盘与移动固态硬盘
一.辨别 USB2.0 和 USB3.0 1.从USB外观上来看,USB2.0通常是白色或黑色,而USB3.0则改观为“高大上”的蓝色接口. 目前,部分笔记本电脑USB接口,已同时提供对USB2.0及 ...
- [PHP] 算法-有序数组旋转后寻找最小值的PHP实现
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组 ...