关于ZAKER 融媒体解决方案 合作 加入

java – 从 Map 中找到的值与相同的 hashcode 和 e.

CocoaChina 11-11

也许不是最好的标题 , 请随时编辑它 .

这是我的代码 ..

import java.util.Map;import java.util.HashMap;public class App { public static void main ( String [ ] args ) { final Foo foo = new Foo ( ) ; final Foo bar = new Foo ( ) ; System.out.println ( "foo equals foo: " + foo.equals ( foo ) ) ; System.out.println ( "foo equals bar: " + foo.equals ( bar ) ) ; System.out.println ( "foo hashcode: " + foo.hashCode ( ) ) ; System.out.println ( "bar hashcode: " + bar.hashCode ( ) ) ; final Map<Foo, Integer> foos = new HashMap<Foo, Integer> ( ) ; foos.put ( foo, -99 ) ; System.out.println ( "foos.getfoo: " + foos.get ( foo ) ) ; System.out.println ( "foos.getbar: " + foos.get ( bar ) ) ; } }class Foo { @Override public boolean equals ( Object o ) { return false; } @Override public int hashCode ( ) { return -1; }}

所以在进一步阅读之前你能猜出下面两个语句的输出是什么吗?

System.out.println ( "foos.getfoo: " + foos.get ( foo ) ) ;System.out.println ( "foos.getbar: " + foos.get ( bar ) ) ;

我希望看到:

nullnull

因为即使 hashCodes 匹配 , 对于任何 Foo 实例的 equals 将始终返回 false, 因此使用 Foo 的实例作为 Map 中的键应该根本没有用 .

但输出是:

:~ $javac App.java:~ $java Appfoo equals foo: falsefoo equals bar: falsefoo hashcode: -1bar hashcode: -1foos.getfoo: -99foos.getbar: null

我错过了什么?当我使用一个哈希码为 -1 并且不等于它自己的对象时 , 如何检索 -99, 但是后来使用相同类型的实例获取 null, 该实例也不等于我在 Map 中所拥有的并且还具有哈希码 -1?

最佳答案

因为 HashMap 的 get ( ) 方法被优化以在查看 equals ( ) 之前首先检查对象引用相等性:

查看节点 < K,V> 由 get ( Object key ) 方法调用的 getNode ( int hash,Object key ) 方法:

final 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 ) { 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;}

这个 :

( k = first.key ) == key

( k = e.key ) == key

参考这个优化 .

此外 , 在这里 , 你违反了 equals ( ) 合同的规则

必须是反身的:

class Foo { @Override public boolean equals ( Object o ) { return false; } ...}

for any non-null reference value x, x.equals ( x ) should return true.

从类违反 equals ( ) 契约的那一刻起 , 您无法保证操纵有缺陷类的实例的类将具有预期的行为 .

以上内容由"CocoaChina"上传发布 查看原文
相关标签 app

觉得文章不错,微信扫描分享好友

扫码分享