Thinking in Java 第17章 容器深入研究(17.8-17.9)
2016-07-21 15:54
423 查看
//声明:部分内容引自《Java编程思想(第四版)》机械工业出版社
自反性。对任意 x ,x.equals(x) 一定返回 true。
对称性。对任意 x 和 y,如果 y.equals(x) 返回 true,则 x.equals(y) 也返回 true。
传递性。对任意 x,y,z,如果有 x.equals(y) 返回 true,y.equals(z) 返回 true,则 x.equals(z) 一定返回 true。
一致性。对任意 x 和 y,如果对象中用于等价比较的信息没有改变,那么无论调用 x.equals(y) 多少次,返回的结果应该保持一致,要么一直是 true,要么一直是 false。
对任何不是 null 的 x,x.equals(null) 一定返回 false。
– 如果要使用自己的类作为 HashMap 的键,必须同时重载 hashCode() 和 equals()。
– 使用散列的目的在于:想要使用一个对象来查找另一个对象。
– 散列的价值在于速度:散列使得查询得以快速进行。散列将键保存在数组中,但是数组并不保存键本身,而是通过键对象生成一个数字,将其作为数组的下标。这个数字就是散列码,由定义在 Object 中的、且可能由你的类覆盖的 hashCode() 方法(散列函数)生成。
为解决数组容量被固定的问题,不同的键可以产生相同的下标,也就是说,可能会有冲突。因此,数组多大就不重要了,任何键总能在数组中找到它的位置。
因此,查询一个值的过程首先就是计算散列码,然后使用散列码查询数组。如果能够保证没有冲突(如果值的数量是固定的,那么就有可能),那就有了一个完美的散列函数,但是这种情况只是特例。通常,冲突由外部链接处理:数组并不直接保存值,而是保存值的 list。然后对 list 中的值使用 equals() 方法进行线性的查询。这部分的查询自然会比较慢,但是,如果散列函数好的话,数组的每个位置就只有较少的值。因此,不是查询整个 list,而是快速地跳到数组的某个位置,只对很少的元素进行比较。这便是 HashMap 会如此快的原因。
– 设计自己的 hashCode()。设计 hashCode() 时最重要的因素就是:无论何时,对同一个对象调用 hashCode() 都应该生成同样的值。此外,也不应该使 hashCode() 方法依赖于具有唯一性的对象信息,尤其是使用 this 的值,这只能产生很糟糕的 hashCode()。因为这样做无法生成一个新的键,使之与 put() 中原始的键值对中的键相同。所以,应该使用对象内有意义的识别信息。
【理解 Map】
– 性能。HashMap 使用散列码,来取代对键的缓慢搜索。使用对象的 hashCode() 方法进行快速查询,此方法能够显著提高性能。【散列与散列码】
– Object.equals() 方法必须满足下列 5 个条件( 默认的 Object.equals() 只是比较对象的地址。):自反性。对任意 x ,x.equals(x) 一定返回 true。
对称性。对任意 x 和 y,如果 y.equals(x) 返回 true,则 x.equals(y) 也返回 true。
传递性。对任意 x,y,z,如果有 x.equals(y) 返回 true,y.equals(z) 返回 true,则 x.equals(z) 一定返回 true。
一致性。对任意 x 和 y,如果对象中用于等价比较的信息没有改变,那么无论调用 x.equals(y) 多少次,返回的结果应该保持一致,要么一直是 true,要么一直是 false。
对任何不是 null 的 x,x.equals(null) 一定返回 false。
– 如果要使用自己的类作为 HashMap 的键,必须同时重载 hashCode() 和 equals()。
– 使用散列的目的在于:想要使用一个对象来查找另一个对象。
– 散列的价值在于速度:散列使得查询得以快速进行。散列将键保存在数组中,但是数组并不保存键本身,而是通过键对象生成一个数字,将其作为数组的下标。这个数字就是散列码,由定义在 Object 中的、且可能由你的类覆盖的 hashCode() 方法(散列函数)生成。
为解决数组容量被固定的问题,不同的键可以产生相同的下标,也就是说,可能会有冲突。因此,数组多大就不重要了,任何键总能在数组中找到它的位置。
因此,查询一个值的过程首先就是计算散列码,然后使用散列码查询数组。如果能够保证没有冲突(如果值的数量是固定的,那么就有可能),那就有了一个完美的散列函数,但是这种情况只是特例。通常,冲突由外部链接处理:数组并不直接保存值,而是保存值的 list。然后对 list 中的值使用 equals() 方法进行线性的查询。这部分的查询自然会比较慢,但是,如果散列函数好的话,数组的每个位置就只有较少的值。因此,不是查询整个 list,而是快速地跳到数组的某个位置,只对很少的元素进行比较。这便是 HashMap 会如此快的原因。
– 设计自己的 hashCode()。设计 hashCode() 时最重要的因素就是:无论何时,对同一个对象调用 hashCode() 都应该生成同样的值。此外,也不应该使 hashCode() 方法依赖于具有唯一性的对象信息,尤其是使用 this 的值,这只能产生很糟糕的 hashCode()。因为这样做无法生成一个新的键,使之与 put() 中原始的键值对中的键相同。所以,应该使用对象内有意义的识别信息。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python动态类型的学习---引用的理解
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c语言实现hashmap(转载)
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序