您的位置:首页 > 编程语言 > Java开发

Thinking in Java 第17章 容器深入研究(17.8-17.9)

2016-07-21 15:54 423 查看
//声明:部分内容引自《Java编程思想(第四版)》机械工业出版社

【理解 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() 中原始的键值对中的键相同。所以,应该使用对象内有意义的识别信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息