当前位置: 首页 > news >正文

岳阳网站优化公司长沙推广公司

岳阳网站优化公司,长沙推广公司,php做的商城网站设计论文,wordpress与joomla与 equals的区别 如果两个引用类型变量使用运算符,那么比较的是地址,它们分别指向的是否是同一地址的对象,结果一定是false,因为两个对象地址必然不同。 不能实现比较对象的值是否相同。 所有对象都有equals方法,默认…
  1. == 与 equals的区别
    如果两个引用类型变量使用==运算符,那么比较的是地址,它们分别指向的是否是同一地址的对象,结果一定是false,因为两个对象地址必然不同。

==不能实现比较对象的值是否相同。

所有对象都有equals方法,默认是Object类的equals,其结果与==一样。

如果希望比较对象的值相同,必须重写equals方法。

public class Object {public native int hashCode();public boolean equals(Object obj) {return (this == obj);}

从源码上可以看到,hashCode()和equals()都和地址相关,因此 new 出来的2个实例,a.equals(b)一定返回false。

  1. 重写equals()
    重写equals()的作用是什么?

如果希望比较对象的值相同,必须重写equals方法。这样可以在equals内自定义比较条件:

public class Student {private  String name;private  String age;private  String qq;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Objects.equals(name, student.name) && Objects.equals(age, student.age) && Objects.equals(qq, student.qq);}
}

如上图所示,自定义的equals()比较条件是Student类的属性,只要姓名、年龄、qq号都相同,则认为是同一个人。

这样是有很大作用的,例如一个Set 可以避免把同一个人加入2次。

但是这样是存在问题,涉及到hashCode

  1. 为什么重写equals方法时必须重写hashcode方法?
    当确定一个对象不会用在集合中时,可以仅重写equals方法不必重写hashcode方法;如果会用在集合中,那么二者必须同时修改,否则会有问题

本来equals方法和hashcode()是不相关的,但是由于我们会在集合中放入我们创建的对象,这样由于存储结构的问题,导致在查找时二者产生了关联。

我们举个例子:

class MyObject {private String name;public MyObject(String name) {this.name = name;}@Overridepublic boolean equals(Object o) {  //重写了equals方法if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;MyObject myObject = (MyObject) o;return Objects.equals(name, myObject.name);}//    @Override
//    public int hashCode() {
//        return Objects.hash(name);
//    }    public static void main(String[] args) {Map<MyObject, Integer> map = new HashMap<MyObject, Integer>();MyObject m1 = new MyObject("a");  //new MyObject("a");创建一个实例map.put(m1, 1);  //以该实例为key,存入一个值,1MyObject m2 = new MyObject("a");  //new MyObject("a");创建一个实例Integer value = map.get(m2);if (value != null) {System.out.println(value);} else {System.out.println("value is null");  //进入该分支,打印}}
}

程序运行结果: value is null

我们往一个HashMap中,放入一个自定义对象 MyObject(“a”)的实例,假设我们重写了equals,然后通过get()方法获取,为何结果为空?

hashmap是一个键值映射的集合类,存储结构为Key+Value,优点是方便快速查找,通过key可以快速找到Value,在存入一个Key+Valuehash元素时,需要先计算Key对应的hash值(计算过程称之为hash算法),hash值决定了最终存放的位置,我们称这个位置为HeadNode,并且如果产生hash碰撞,一般会采用链式结构扩展这个HeadNode,这个链也常称作桶,允许包含一组值。
当key是一个对象类型时,,例如MyObject,我们需要重写equals()方法,此时2个对象的值相等等价于这2个对象是同一个对象,存在MyObject的2个实例对象,m1和m2,我们认定这俩对象”相等“,先利用m1作为key,存入hashmap,值为v1,此时,我们期望通过m2也能从hashmap中得到v1,在不重写hashcode的情况下,get(m2)会返回null ,为什么?

原因是hash值的计算借助hashcode方法,该方法的默认算法实现和对象的地址有关,而m1和m2被创建后,内存地址肯定不同,因此,在没有重写hashcode()方法时,所有的对象存入hashmap后,m1的hashcode是h1,m2的hashcode是h2, h1!=h2 ,那么get(m2) 就无法找到h1位置,也就无法返回v1

重写hashcode()方法目的是确保h1=h2,那么就get(m2) 就能找到h1位置,也就可以返回v1
在这里插入图片描述
在这里插入图片描述
如上面的图,如果二者同时修改的话,那么 h1和h2相同,那么就可以在同一个链中找到值相同的对象;否则仅重写equals方法不重写hashcode方法,h1和h2不同,就落到不同的链上,那么就找不到了;

HashMap的get()方法源码

public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {
//入口public V get(Object key) {Node<K,V> e;return (e = getNode(hash(key), key)) == null ? null : e.value;}//间接调用 getNodefinal Node<K,V> getNode(int hash, Object key) {Node<K,V>[] tab; Node<K,V> first, e; int n; K k;if ((tab = table) != null && (n = tab.length) > 0 &&(first = tab[(n - 1) & hash]) != null) {   //计算hash,如果不重写,那么hash的值就和内存地址相关if (first.hash == hash && // always check first node((k = first.key) == key || (key != null && key.equals(k))))return first;if ((e = first.next) != null) {if (first instanceof TreeNode)return ((TreeNode<K,V>)first).getTreeNode(hash, key);do {if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))return e;} while ((e = e.next) != null);}}return null;}

3.1 Hash算法
先用一张图看下什么是Hash
在这里插入图片描述
Hash是散列的意思,就是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。关于散列值,有以下几个关键结论:

如果散列表中存在和散列原始输入K相等的记录,那么K必定在f(K)的存储位置上 ,即多次计算hash值一定相同
不同关键字经过散列算法变换后可能得到同一个散列地址,这种现象称为碰撞
如果两个Hash值不同(前提是同一Hash算法),那么这两个Hash值对应的原始输入必定不同
3.2 HashCode()
然后讲下什么是HashCode,总结几个关键点:

1、HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的

2、如果两个对象equals相等,那么这两个对象的HashCode一定也相同

3、如果对象的equals方法被重写,那么对象的HashCode方法也一定重写

4、如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

即hashmap的底层实现,为了实现方便的查找,采用数组+链表,数组是hash的结果,链表是碰撞的解决方案。

这样,当在hashmap里面查找某个对象时,先通过hash快速找到对应的链表,然后在链表上逐个进行equals()比较,否则,需要在所有的元素上逐一进行比较,时间复杂度比较差。

先找链,再在链上进行值的比较
因此,如果改写了equals(),而不改写hashcode的话,Object内默认hashcode()方法必定不同的(new 出对象的地址一定不同),这样hashmap存储的2个对象,都在不同的链上,这样无法进行equals()比较。

http://www.yidumall.com/news/14773.html

相关文章:

  • 徐州建站推广seo排名哪家有名
  • 网站建设遇到问题解决方案南昌seo专业团队
  • 代做标书网站值得收藏的五个搜索引擎
  • 在线做家装设计的网站免费建站软件
  • 一级a做爰片免费网站 视频灰色推广
  • 自制响应式网站九江seo优化
  • 做木箱的网站西安seo排名优化推广价格
  • 秦皇岛网站定制哪家好口碑营销的模式
  • 怎么看别人网站是怎么做的seo每日工作内容
  • 网站服务建设跨境电商平台
  • 国美的网站做的怎么样58网络推广
  • 多合一建网站广告公司网上接单平台
  • 创建全国文明城市手抄报内容seo运营是什么意思
  • 男直接做的视频网站百度网址导航
  • 界面设计优秀的网站有哪些有哪些可以免费推广的平台
  • 自己建网站可以赚钱吗网络推广公司运营
  • 网站做3年3年包括什么sem广告
  • 哪些网站可以做外贸军事新闻俄乌最新消息
  • 抓取网站源码怎么做镜像黄页引流推广
  • 设计师的网站有哪些深圳最新消息
  • 上海疫情最新统计seo网站优化报价
  • 绍兴本地网站建设网络营销策划书3000字
  • 怎么做网站流量加强网络暴力治理
  • wordpress添加形式吉林seo排名公司
  • 安溪网站建设站长统计网站
  • iis端口相同不同网站建设厦门seo顾问
  • 潍坊免费模板建站百度客服电话24小时客服电话
  • 开发工程师网站开发工程师网络营销师是干什么的
  • 滕州外贸网站建设郑州网站营销推广公司
  • 昌都市网站建设模板建站多少钱