- 浏览: 1010348 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (394)
- OSGI (14)
- 多线程 (10)
- 数据库 (30)
- J2ME (1)
- JAVA基础知识 (46)
- 引用包 (1)
- 设计模式 (7)
- 工作流 (2)
- Ubuntu (7)
- 搜索引擎 (6)
- QT (2)
- Ubuntu下编程 (1)
- 小程序 (2)
- UML (1)
- Servlet (10)
- spring (16)
- IM (12)
- 文档视频转为flash格式在线播放 (19)
- Maven (8)
- 远程调用 (2)
- PHPRPC (1)
- EXTJS学习 (2)
- Hibernate (16)
- 技术文章 (38)
- flex (5)
- 海量数据处理 (5)
- FTP (8)
- JS (10)
- Struts (1)
- hibernate search (13)
- JQuery (2)
- EMail (3)
- 算法 (4)
- SVN (7)
- JFreeChart (4)
- 面试 (4)
- 正规表达式 (2)
- 数据库性能优化 (10)
- JVM (6)
- Http Session Cookie (7)
- 网络 (12)
- Hadoop (2)
- 性能 (1)
最新评论
-
hy1235366:
能够随便也发一下,你退火算法程序使用的DistanceMatr ...
模拟退火算法总结(含例子)(转) -
梅强强:
感谢分享。。帮大忙了
swftools转换文件时线程堵塞问题的解决方法 -
wenlongsust:
openoffice和文件不在同一个服务器上,用过吗?
[JODConverter]word转pdf心得分享(转) -
2047699523:
如何在java Web项目中开发WebService接口htt ...
利用Java编写简单的WebService实例 -
abingpow:
唉,看起来好像很详细很不错的样子,可惜不是篇面向初学者的文章, ...
Spring与OSGi的整合(二)(转)
在面试的时候被问到hashCode的作用,那时我没答好,所以现在在网上找了一些例子和讲解,现在总结一下:
哈希码产生的依据:
哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。
下面给出几个常用的哈希码的算法:
1:Object类的hashCode.返回对象的内存地址经过处理后的结构,由于每个对象的内存地址都不一样,所以hashcode可以做到尽可能的不一样,但我们要清楚一点,既然是用到hash技术,就是要解决冲突的,所以hashcode是会出现相同的时候,我们可以将hashCode相同的看成放入同一个桶中。
package com.tools; import java.util.ArrayList; /** * 此方法的作用是证明 java.lang.Object的hashcode 不是代表 对象所在内存地址。 * 我产生了10000个对象,这10000个对象在内存中是不同的地址,但是实际上这10000个对象 * 的hashcode的是完全可能相同的 */ public class HashCodeMeaning { public static void main(String[] args) { ArrayList list = new ArrayList(); int numberExist=0; System.out.println("______________证明hashcode的值不是内存地址________________"); //证明hashcode的值不是内存地址 for (int i = 0; i < 10000; i++) { Object obj=new Object();//obj是内存地址 if (list.contains(obj.hashCode())) {//获得对象的hashCode System.out.println(obj.hashCode() +" exists in the list. "+ i); numberExist++; } else { list.add(obj.hashCode()); } } System.out.println("repetition number:"+numberExist);//和重复的hashCode,说明它不是内存地址 System.out.println("list size:"+list.size()); System.out.println("____________证明内存地址是不同的_______________"); //证明内存地址是不同的。 numberExist=0; list.clear(); for (int i = 0; i < 10000; i++) { Object obj=new Object();//获得的是对象的内存地址 if (list.contains(obj)) {//直接加入内存地址 System.out.println(obj +" exists in the list. "+ i); numberExist++; } else { list.add(obj); } } //内存地址没重复 System.out.println("repetition number:"+numberExist); System.out.println("list size:"+list.size()); } }
3:Integer类,返回的哈希码就是Integer对象里所包含的那个整数的数值,例如Integer i1=new Integer(100),i1.hashCode的值就是100 。由此可见,2个一样大小的Integer对象,返回的哈希码也一样。 public native int hashCode();
到 OpenJDK 下载 OpenJDK 的源代码,解压后找到 hotspot/src/share/vm/runtime 目录,里面有个 synchronizer.cpp 文件,找到:
这个函数基本上就在这了,原始的 hashCode 在 jdk/src/share/native/java/lang/Object.c 这个文件中,调来调去就调到上面那个函数去了。
2:String类的hashCode.根据String类包含的字符串的内容,根据一种特殊算法返回哈希码,只要字符串内容相同,返回的哈希码也相同,这个可以简单实现如将串的各个字母相与的结果作为hashcode,而sun实现比这个复杂多。
由于是native方法,跟OS的处理方式相关,源代码里仅仅有一个声明罢了。我们有兴趣的话完全可以去深究它的hashCode到底是由OS怎么样产生的呢?但笔者建议最重要的还是先记住使用它的几条原则吧!首先如果equals()方法相同的对象具有相通的hashCode,但equals ()对象不相通的时候并不保证hashCode()方法返回不同的整数。而且下一次运行同一个程序,同一个对象未必还是当初的那个hashCode() 哦。intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {
if (UseBiasedLocking) {
// NOTE: many places throughout the JVM do not expect a safepoint
// to be taken here, in particular most operations on perm gen
// objects. However, we only ever bias Java instances and all of
// the call sites of identity_hash that might revoke biases have
// been checked to make sure they can handle a safepoint. The
// added check of the bias pattern is to avoid useless calls to
// thread-local storage.
if (obj->mark()->has_bias_pattern()) {
// Box and unbox the raw reference just in case we cause a STW safepoint.
Handle hobj (Self, obj) ;
// Relaxing assertion for bug 6320749.
assert (Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(),
"biases should not be seen by VM thread here");
BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
obj = hobj() ;
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
}
// hashCode() is a heap mutator ...
// Relaxing assertion for bug 6320749.
assert (Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(), "invariant") ;
assert (Universe::verify_in_progress() ||
Self->is_Java_thread() , "invariant") ;
assert (Universe::verify_in_progress() ||
((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant") ;
ObjectMonitor* monitor = NULL;
markOop temp, test;
intptr_t hash;
markOop mark = ReadStableMark (obj);
// object should remain ineligible for biased locking
assert (!mark->has_bias_pattern(), "invariant") ;
if (mark->is_neutral()) {
hash = mark->hash(); // this is a normal header
if (hash) { // if it has hash, just return it
return hash;
}
hash = get_next_hash(Self, obj); // allocate a new hash code
temp = mark->copy_set_hash(hash); // merge the hash code into header
// use (machine word version) atomic operation to install the hash
test = (markOop) Atomic::cmpxchg_ptr(temp, obj->mark_addr(), mark);
if (test == mark) {
return hash;
}
// If atomic operation failed, we must inflate the header
// into heavy weight monitor. We could add more code here
// for fast path, but it does not worth the complexity.
} else if (mark->has_monitor()) {
monitor = mark->monitor();
temp = monitor->header();
assert (temp->is_neutral(), "invariant") ;
hash = temp->hash();
if (hash) {
return hash;
}
// Skip to the following code to reduce code size
} else if (Self->is_lock_owned((address)mark->locker())) {
temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
assert (temp->is_neutral(), "invariant") ;
hash = temp->hash(); // by current thread, check if the displaced
if (hash) { // header contains hash code
return hash;
}
// WARNING:
// The displaced header is strictly immutable.
// It can NOT be changed in ANY cases. So we have
// to inflate the header into heavyweight monitor
// even the current thread owns the lock. The reason
// is the BasicLock (stack slot) will be asynchronously
// read by other threads during the inflate() function.
// Any change to stack may not propagate to other threads
// correctly.
}
// Inflate the monitor to set hash code
monitor = ObjectSynchronizer::inflate(Self, obj);
// Load displaced header and check it has hash code
mark = monitor->header();
assert (mark->is_neutral(), "invariant") ;
hash = mark->hash();
if (hash == 0) {
hash = get_next_hash(Self, obj);
temp = mark->copy_set_hash(hash); // merge hash code into header
assert (temp->is_neutral(), "invariant") ;
test = (markOop) Atomic::cmpxchg_ptr(temp, monitor, mark);
if (test != mark) {
// The only update to the header in the monitor (outside GC)
// is install the hash code. If someone add new usage of
// displaced header, please update this code
hash = test->hash();
assert (test->is_neutral(), "invariant") ;
assert (hash != 0, "Trivial unexpected object/monitor header usage.");
}
}
// We finally get the hash
return hash;
}
OpenJDK 6 的下载页面:http://download.java.net/openjdk/jdk6/ 上面有个 46.9MB 的 tar.gz 文件,下载回来后是整个 JDK(JVM、JDK 工具和 J2SE 类库和底层类库)的源代码,解压后有 254MB,大约有 28750 个文件。
2. 关于重载hashCode()与Collection框架的关系
笔者曾经听一位搞Java培训多年的前辈说在他看来hashCode方法没有任何意义,仅仅是为了配合证明具有同样的hashCode会导致equals 方法相等而存在的。连有的前辈都犯这样的错误,其实说明它还是满容易被忽略的。那么hashCode()方法到底做什么用?
学过数据结构的课程大家都会知道有一种结构叫hash table,目的是通过给每个对象分配一个唯一的索引来提高查询的效率。那么Java也不会肆意扭曲改变这个概念,所以hashCode唯一的作用就是为支持数据结构中的哈希表结构而存在的,换句话说,也就是只有用到集合框架的 Hashtable、HashMap、HashSet的时候,才需要重载hashCode()方法,
这样才能使得我们能人为的去控制在哈希结构中索引是否相等。笔者举一个例子:
曾经为了写一个求解类程序,需要随机列出1,2,3,4组成的不同排列组合,所以笔者写了一个数组类用int[]来存组合结果,然后把随机产生的组合加入一个HashSet中,就是想利用HashSet不包括重复元素的特点。可是HashSet怎么判断是不是重复的元素呢?当然是通过 hashCode()返回的结果是否相等来判断啦,可做一下这个实验:
int[] A = {1,2,3,4};
int[] B = {1,2,3,4};
System.out.println(A.hashCode());
System.out.println(B.hashCode());
这明明是同一种组合,却是不同的hashCode,加入Set的时候会被当成不同的对象。这个时候我们就需要自己来重写hashCode()方法了,如何写呢?其实也是基于原始的hashCode(),毕竟那是操作系统的实现, 找到相通对象唯一的标识,实现方式很多,笔者的实现方式是:
首先重写了toString()方法:
return A[0]“+” A[1]“+” A[2]“+” A[3]; //显示上比较直观
然后利用toString()来计算hashCode():
return this.toString().hashCode();
这样上述A和B返回的就都是”1234”,在测试toString().hashCode(),由于String在内存中的副本是一样的,”1234”.hashCode()返回的一定是相同的结果。
说到这,相信大家能理解得比我更好,今后千万不要再误解hashCode()方法的作用。
其余的方法呢?nofigy()、notifyAll()、clone()、wait()都是native方法的,说明依赖于操作系统的实现。最后一个有趣的方法是finalize(),类似C++的析构函数,签名是protected,证明只有继承扩展了才能使用,方法体是空的,默示什么也不做。它的作用据笔者的了解仅仅是通知JVM此对象不再使用,随时可以被销毁,而实际的销毁权还是在于虚拟机手上。那么它真的什么也不做麽?未必,实际上如果是线程对象它会导致在一定范围内该线程的优先级别提高,导致更快的被销毁来节约内存提高性能。其实从常理来说,我们也可以大概这样猜测出jvm做法的目的。
发表评论
-
Java线程(二):线程同步synchronized和volatile(转)
2014-03-17 00:09 918转载自:http://blog.csdn.net/ghsau ... -
浅谈Java多线程的同步问题(l转)
2014-03-17 00:07 963非常好的使用线程同步的文章 转载自http://www.c ... -
JVM的垃圾回收机制详解和调优(转)
2013-06-20 10:31 7441.JVM的gc概述 gc即垃圾 ... -
深入探讨 Java 类加载器(转)
2013-06-20 10:17 903转载自:http://www.ibm.com/develop ... -
java反射详解(推荐转)
2013-05-15 10:42 907载自:http://www.cnblogs.com/roll ... -
java静态方法、非静态代码块{}、静态代码块static{}(转)
2012-07-13 14:33 1514转自:http://www.cn-java.com/www1/ ... -
error 与 Exception区别(转)
2012-07-13 14:31 1105Error类和Exception类都继承自Throwab ... -
java面试题有哪些常见的(转)
2012-07-13 14:30 1223第一,谈谈final, finally, finaliz ... -
java Math.round()(转)
2012-07-11 14:17 1215public class MathTest { ... -
Java异常的分类(转)
2012-07-11 08:57 1073转载自:http://blog.csdn.net/ilibab ... -
java 内联函数(转)
2012-06-28 23:40 1857以前用过C++,知道它 ... -
堆栈,堆栈,堆和栈的区别(转)
2011-05-08 00:36 1213不防看看这篇文章:http://www.cppblog.com ... -
第二十章 指针 二 为指针分配和释放空间(转)
2011-05-08 00:10 1523载自<白话c++>:http://17de.com ... -
数据结构中各种时间复杂度(转)
2011-05-06 09:58 2817(1)冒泡排序 冒泡排序就是把小的元素往 ... -
C#之int挑战Java之Integer(转)
2011-04-28 14:24 1368可能有些图会看不到,可以到转载处去阅读:http://kb.c ... -
Java: 堆 & 栈(转)
2011-04-28 14:16 1429栈是运行时的单位,而堆是存储的单位。栈解决程序的运行问题,即程 ... -
native2ascii 使用方法 及 Java字符编码(转)
2011-04-18 01:17 2761在做Java开发的时候,常 ... -
Unicode,ISO-8859,GBK,UTF-8编码及相互转换(java)(转)
2011-04-18 01:15 69181、函数介绍在Java中,字符串用统一的Unicode编码 ... -
GBK与UTF-8 转换乱码详解(转)
2011-04-18 01:07 3513getBytes 的功能是将字符转换成字节数组, gbk. ... -
Java TreeMap的简单实现(转)
2011-04-18 00:29 1125TreeMap的实现与二叉搜索树显示,其对应的节点格式为 E ...
相关推荐
### 深入理解 HashCode 方法 #### 一、HashCode 的基本概念与作用 在 Java 编程语言中,`HashCode` 是一个非常重要且基础的概念。简单来说,`HashCode` 是一个整数值,用于快速定位对象的位置。在 Java 中,每一个...
《深入理解HashCode方法》 HashCode方法在Java编程中扮演着至关重要的角色,尤其是在涉及对象存储和查找效率的数据结构,如HashMap和Hashtable中。一个对象的HashCode是一个简单的哈希算法实现,尽管它相对复杂的...
深入理解Java中HashCode方法 Java中的hashCode方法是每个类都需要实现的重要方法之一,它的主要作用是将对象的数据转换为一个32位的整数,用于标识对象的唯一性。在Java的所有类中,Object类是最顶层的父类,它定义...
《深入HashCode》 在计算机科学领域,特别是在Java和许多其他面向...理解和正确实现`hashCode()`是每个程序员必备的技能之一。通过合理设计和优化`hashCode()`方法,我们可以提高程序的性能并确保数据结构的正确性。
为了更好地理解`hashCode`的作用及其在实际开发中的重要性,我们可以从以下几个方面进行深入探讨: #### 1. 基本概念 `hashCode`方法是`java.lang.Object`类中的一个方法,所有Java类都继承自`Object`类,因此每个...
本文将详细介绍 HashCode 的作用和重要性,为读者提供一个深入了解 HashCode 的机会。 HashCode 的作用 在 Java 中,HashSet、HashMap 等集合类的实现中,都是通过 HashCode 来实现对象的唯一性和快速查找的。那么...
本主题将深入探讨如何利用反射技术绕过编译器的一些限制,并介绍hashcode在高级应用中的用法。 首先,让我们理解反射的基本概念。在Java中,反射提供了一种方式,使我们能够在运行时动态地获取类的信息(如类名、...
深入理解equals和hashCode方法 equals和hashCode方法是Java中Object类提供的两个重要方法,对以后的学习有很大的帮助。本文将深入剖析这两个方法,帮助读者更好地理解和使用它们。 equals方法 equals方法是用于...
在Java编程语言中,`hashCode()`和`equals()`方法是非常重要的概念,它们不仅对于深入理解Java内存管理至关重要,也是实现自定义类的关键部分之一。本文将详细介绍这两个方法的工作原理、使用场景以及它们之间的关系...
总之,理解并正确重写 `equals()` 和 `hashCode()` 方法对于编写高质量的Java代码至关重要,这直接影响到对象比较的逻辑以及使用哈希表的数据结构的效率。通过遵循上述原则和最佳实践,我们可以确保对象的比较行为...
本篇将深入探讨ArrayList与HashSet的区别,并分析Hashcode在其中的作用。 ArrayList是基于动态数组实现的,它提供了按索引访问元素的能力,就像在数组中一样。由于内部维护了一个数组,ArrayList保证了元素的顺序性...
深入理解hashCode()和equals()方法的重要性,以及Comparable接口和Comparator接口在排序中的作用。 输入输出流是Java处理数据传输的关键,考试会涉及文件类,如File,以及各种输入/输出流,包括FileInputStream、...
总的来说,理解并正确使用`equals()`和`hashCode()`方法对于编写高质量的Java代码至关重要,尤其是在处理集合框架中的对象时。这两个方法的合理实现能确保对象比较的正确性和哈希表操作的效率。希望这个深入解析能...
综上所述,正确理解和使用`equals`和`hashCode`方法对于编写高质量的Java程序至关重要。通过对这两个方法的合理覆盖,可以有效地提高数据结构(如`HashSet`和`HashMap`)的操作效率,同时也能更好地支持对象之间的...
本文将深入探讨内存泄漏及其可能导致的内存溢出问题,以及如何识别和解决这些问题。 首先,我们需要明确什么是内存泄漏。内存泄漏是指程序中已经分配的内存块在不再使用后,由于编程错误或设计缺陷,没有被正确地...
在深入探讨`hashCode`方法之前,我们需要了解Java集合框架的基本概念。Java集合框架主要包括两大类集合:`List`和`Set`。 - **List**:这是一个有序集合,允许元素重复。 - **Set**:这是一个不允许元素重复的无序...
通过对 hashCode 和 equals 方法的深入分析,我们可以更好地理解 Java 集合的实现原理和哈希表的工作机制。 一、hashCode 方法简介 hashCode 方法是 Java 中 Object 类的一个方法,用于返回对象的哈希码值。这个...
本篇文章将深入探讨如何在Java中生成一个合适的`hashCode()`方法,以及在开发过程中应该注意的关键点。 首先,理解`hashCode()`方法的作用至关重要。当我们将一个对象放入哈希表时,`hashCode()`方法被调用以生成一...
下面我们将深入探讨 Java 中 HashCode 重复的可能性。 首先,让我们了解什么是 Hash Code。Hash Code 是一种对象标识符,它用于标识对象的唯一性。在 Java 中,每个对象都有一个 Hash Code,它可以通过 hashCode() ...