A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 殷婷婷 中级黑马   /  2013-11-4 11:53  /  1860 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. import java.util.*;
  2. class LinkedListDemo
  3. {
  4.         public int hashCode()
  5.         {
  6.                 return 99;
  7.         }
  8.         public static void main(String[] args)
  9.         {
  10.                 LinkedListDemo lld = new LinkedListDemo();//哈希值是99
  11.                 LinkedListDemo lldd = new LinkedListDemo();//哈希值是99
  12.                 System.out.println(lld);
  13.                 System.out.println(lldd);
  14.         }
  15. }
复制代码
不明白,两个或多个对象怎么能共用一个哈希值呢?它们究竟是怎么存储的?

评分

参与人数 1黑马币 +1 收起 理由
乔兵 + 1

查看全部评分

4 个回复

倒序浏览
public int hashCode() 这个已经说的很清楚了
hashCode 只是一个方法的返回值,更进一步来说,只是一个 int型 整数
跟存储其实没什么关系,说hashCode用于存储是说Hashtable这种无序数据存储方式采用hashCode作为存储参数,使用一个天书一般的算法实现
其实如果类不实现hashtable的话hashcode的作用不是很明显
一般说重写equals方法时也要重写hashcode只是为了遵循hash约定

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
每个自定义类都继承自Object,LinkedListDemo重写hashcode()方法之后就是调用自己的方法了,返回都是99,直接打印的话就是哈希值,一般hashcode()计算出的值为jvm中内存地址,上面的LinkedListDemo自定义后就是99,至于hashcode()底层是怎么计算出来的,可以参考java的源代码:
  1. intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
  2.   if (UseBiasedLocking) {
  3.     // NOTE: many places throughout the JVM do not expect a safepoint
  4.     // to be taken here, in particular most operations on perm gen
  5.     // objects. However, we only ever bias Java instances and all of
  6.     // the call sites of identity_hash that might revoke biases have
  7.     // been checked to make sure they can handle a safepoint. The
  8.     // added check of the bias pattern is to avoid useless calls to
  9.     // thread-local storage.
  10.     if (obj->mark()->has_bias_pattern()) {
  11.       // Box and unbox the raw reference just in case we cause a STW safepoint.
  12.       Handle hobj (Self, obj) ;         
  13.       // Relaxing assertion for bug 6320749.
  14.       assert (Universe::verify_in_progress() ||
  15.               !SafepointSynchronize::is_at_safepoint(),
  16.              "biases should not be seen by VM thread here");
  17.       BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
  18.       obj = hobj() ;
  19.       assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
  20.     }
  21.   }

  22.   // hashCode() is a heap mutator ...
  23.   // Relaxing assertion for bug 6320749.
  24.   assert (Universe::verify_in_progress() ||
  25.           !SafepointSynchronize::is_at_safepoint(), "invariant") ;
  26.   assert (Universe::verify_in_progress() ||
  27.           Self->is_Java_thread() , "invariant") ;
  28.   assert (Universe::verify_in_progress() ||
  29.          ((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;

  30.   ObjectMonitor* monitor = NULL;
  31.   markOop temp, test;
  32.   intptr_t hash;
  33.   markOop mark = ReadStableMark (obj);

  34.   // object should remain ineligible for biased locking
  35.   assert (!mark->has_bias_pattern(), "invariant") ;

  36.   if (mark->is_neutral()) {
  37.     hash = mark->hash();              // this is a normal header
  38.     if (hash) {                       // if it has hash, just return it
  39.       return hash;
  40.     }
  41.     hash = get_next_hash(Self, obj);  // allocate a new hash code
  42.     temp = mark->copy_set_hash(hash); // merge the hash code into header
  43.     // use (machine word version) atomic operation to install the hash
  44.     test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
  45.     if (test == mark) {
  46.       return hash;
  47.     }
  48.     // If atomic operation failed, we must inflate the header
  49.     // into heavy weight monitor. We could add more code here
  50.     // for fast path, but it does not worth the complexity.
  51.   } else if (mark->has_monitor()) {
  52.     monitor = mark->monitor();
  53.     temp = monitor->header();
  54.     assert (temp->is_neutral(), "invariant") ;
  55.     hash = temp->hash();
  56.     if (hash) {
  57.       return hash;
  58.     }
  59.     // Skip to the following code to reduce code size
  60.   } else if (Self->is_lock_owned((address)mark->locker())) {
  61.     temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
  62.     assert (temp->is_neutral(), "invariant") ;
  63.     hash = temp->hash();              // by current thread, check if the displaced
  64.     if (hash) {                       // header contains hash code
  65.       return hash;
  66.     }
  67.     // WARNING:
  68.     //   The displaced header is strictly immutable.
  69.     // It can NOT be changed in ANY cases. So we have
  70.     // to inflate the header into heavyweight monitor
  71.     // even the current thread owns the lock. The reason
  72.     // is the BasicLock (stack slot) will be asynchronously
  73.     // read by other threads during the inflate() function.
  74.     // Any change to stack may not propagate to other threads
  75.     // correctly.
  76.   }

  77.   // Inflate the monitor to set hash code
  78.   monitor = ObjectSynchronizer::inflate(Self, obj);
  79.   // Load displaced header and check it has hash code
  80.   mark = monitor->header();
  81.   assert (mark->is_neutral(), "invariant") ;
  82.   hash = mark->hash();
  83.   if (hash == 0) {
  84.     hash = get_next_hash(Self, obj);
  85.     temp = mark->copy_set_hash(hash); // merge hash code into header
  86.     assert (temp->is_neutral(), "invariant") ;
  87.     test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
  88.     if (test != mark) {
  89.       // The only update to the header in the monitor (outside GC)
  90.       // is install the hash code. If someone add new usage of
  91.       // displaced header, please update this code
  92.       hash = test->hash();
  93.       assert (test->is_neutral(), "invariant") ;
  94.       assert (hash != 0, "Trivial unexpected object/monitor header usage.");
  95.     }
  96.   }
  97.   // We finally get the hash
  98.   return hash;
  99. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
hashCode()是一本地方法,也就是说当new一个对象的时候,都会有一个hash码,计算hash码用到相应的hash算法,我个人认为之所以hashcode()方法是一个本地方法,是应为java中的对象的hash码的得出是通过本地系统提供的hash算法(个人理解,有误请指正),还有java中 对象的hashcode并不是指对象的物理地址。你复写hashcode方法后,就是说对象的hashcode是按你写的方法来计算而已,在楼主的程序中你是new了两个对象,所以内存地址肯定是不一样的,但是在你定义的类中复写里hashcode方法,而且是返回一个确定的值,所以他们hash码肯定是一致的。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
先给大体介绍一下吧。
Java中的集合(Collection)有两类,一类是List,再有一类是Set。
你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。 也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。    于是,Java采用了哈希表的原理。
初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。   
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。
如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,
就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。
所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。   
所以,Java对于eqauls方法和hashCode方法是这样规定的:
1、如果两个对象相同,那么它们的hashCode值一定要相同;
2、如果两个对象的hashCode相同,它们并不一定相同     上面说的对象相同指的是用eqauls方法比较。   
你当然可以不按要求去做了,但你会发现,相同的对象可以出现在Set集合中。同时,增加新元素的效率会大大下降。
楼主的问题就是,底层都会调用public int hashCode()方法,楼主自行实现并覆盖了父类hashCode,代码中 return 99; 当然返回99了

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马