情景上这样的:我有一个重写了equals方法的类,该类源码如下。然后用一程序将此类多次循环put到HashMap中去,但每次put到1500次左右时,就会出现NullPointerException。
在map.put的方法中,会先去判断put进去的对象是否已经存在于map中,判断方法调用的就是该对象的重写的equals方法,如果说我写的equals有问题的话,为什么前1000多次左右不会出现问题而在最后出现问题呢?起初以为是放到HashMap中的对象太大会出现内存溢出,但并未出现outofmemory异常,用JProfiler进行监测时也发现和heap的使用也没关系……有哪位兄弟帮我解释一下……
重写了equals方法的类:
public class myPolSchema {
// @Field
private String GrpContNo;
private String GrpPolNo;
public String getGrpContNo() {
return GrpContNo;
}
public void setGrpContNo(String aGrpContNo) {
GrpContNo = aGrpContNo;
}
public String getGrpPolNo() {
return GrpPolNo;
}
public void setGrpPolNo(String aGrpPolNo) {
GrpPolNo = aGrpPolNo;
}
public boolean equals(Object otherObject) {
if (this == otherObject)
return true;
if (otherObject == null)
return false;
if (getClass() != otherObject.getClass())
return false;
myPolSchema other = (myPolSchema) otherObject;
return GrpContNo.equals(other.getGrpContNo())
&& GrpPolNo.equals(other.getGrpPolNo());
}
}
测试类:
import java.util.* ;
public class MultiThreading{
// implements Runnable
Map m=Collections.synchronizedMap(new HashMap());
//HashMap m=new HashMap();
Hashtable t=new Hashtable();
public myPolSchema polschema;
public void run()
{
polschema=new myPolSchema();
m.put(polschema, "UPDATE");
System.out.println("put end at " + new Date());
}
public static void main(String[] args) throws Exception {
MultiThreading t=new MultiThreading();
for(int i=0;i <=25000;i++){
try{
t.run();
//Thread.sleep(100);
}
catch(Exception ex){
//在我本地测试时当运行大概1500左右次的时间就会抛出NullPointerException
System.out.println("i is: " + i);
throw ex;
}
}
}
}
如果您从源码上看不出来我所说的问题,在此处下载源码……
重写equals的同时需要重写hashCode方法
可以参考:
http://zhangjunhd.blog.51cto.com/113473/71571
建议看《Effective Java》其中关于重写equals和hashCode的内容。
希望以上回复对你有帮助。
重写hashCode()方法。
equals方法可能没有错,但是可能默认的hashcode方法出问题了
effective java上面写道"重写equals方法,也要重写hashcode方法"
在一般情况下,可能你不重写hashcode也没问题,但是当你这种情况时,你使用了map容器,可能两个对象equals==true 但是两个对像的hashcode却不同,就可能发生你这种情况
我修改了一下的代码后,发现没有问题了。
polschema = new myPolSchema();
polschema.setGrpContNo("1");
polschema.setGrpPolNo("2");
m.put(polschema, "UPDATE");
觉得最初的原因是你用的Map m=Collections.synchronizedMap(new HashMap());
除的问题,haspMap是允许为空的,但是里面的属性为空时你不能用来判断。
GrpContNo.equals(other.getGrpContNo())
&& GrpPolNo.equals(other.getGrpPolNo()); 中GrpContNo是空的,至于你前面为什么可以插入一下,不是很理解。
怀疑是[quote]Map m=Collections.synchronizedMap(new HashMap()); [/quote]原因
因为我用hashtable时一个都插不进去
改为:
[code="java"]import java.util.* ;
public class MultiThreading{
// implements Runnable
Map m=Collections.synchronizedMap(new HashMap());
//HashMap m=new HashMap();
Hashtable t=new Hashtable();
public myPolSchema polschema;
public void run(int i)
{
polschema=new myPolSchema();
polschema.setGrpContNo(Integer.toString(i));
polschema.setGrpPolNo(Integer.toString(i));
m.put(polschema, "UPDATE");
System.out.println("put end at " + new Date());
}
public static void main(String[] args) throws Exception {
MultiThreading t=new MultiThreading();
for(int i=0;i <=25000;i++){
try{
t.run(i);
//Thread.sleep(100);
}
catch(Exception ex){
//在我本地测试时当运行大概1500左右次的时间就会抛出NullPointerException
System.out.println("i is: " + i);
throw ex;
}
}
}
}
[/code]
即可,这样hashCode都不会重复,不会再抛异常了(因为你插入的对象的属性都为空串,hashCode很容易重)。