问题的起因是编写的以下代码今天出现了问题:
private List<Integer> ids = new ArrayList<Integer>(); //new a list to store user id
......
ids.add(user.getID()); //add user id to ids
......
ids.remove(user.getID()); //remove user id from ids
细心的朋友很容易就找到问题所在。因为List提供两个remove方法:
remove(int index)
remove(Object o)
而我使用Integer作为泛型,这样调用remove方法时,编译器自动将Integer转化为了Int,所以实际调用的是remove(int index)这个方法。显然,我的本意是调用remove(Object o)。这样的问题,如果不是程序抛出IndexOutBoudsException,对于一向粗心的我还一直蒙在鼓里。
本文的重点在于解决此问题的过程中引发的一系列思考,并结合最近再次拜读《Effective Java》这本经典著作的结果给出了一些对java语言的心得体会。
回到问题本身来,最直接的解决方案如下:
ids.remove(Integer.valueOf(user.getID()));
经过测试,该方案是可行的。
心血来潮,我提出了以下新的方案,它是否可行呢:
ids.remove(new Integer(user.getID()));
初步分析,应该是不行的,因为传入的参数是一个新的Integer对象,而与原来的Integer是不相等的,所以remove操作将失败。
遗憾的是,以上分析是错误的,事实证明第二种方案也是可行的。为什么呢?
回想起《Effective Java》一书中,介绍"equals"方法的一段,有了启发。以上分析的结论是基于remove方法是以对象引用是否相等来判断,即通过“==”操作符来判断是否存在指定移除的对象。然而,它有没有可能是通过Integer对象的"equals"方法来判断的呢?如果是,两个不同的Integer对象,他们的值相同时,"equals"方法是否返回true呢?
验证第二个疑问很简单,写段程序验证一下就可。事实上,两个不同的Integer对象,他们的值相同时,"equals"方法是返回true的。因为Integer类override了Object.equals方法
验证第一个疑问也很简单,查看JDK源码:)
这时候,我突然想起了大学英语课文中关于爱因斯坦研究玩具鸟原理的文章(MS内容是这样的吧,大意是爱因斯坦想知道一只玩具鸟是怎么发出叫声的,而他一直不愿意拆开玩具来知道答案,直到最后他经过冥思苦想来得到答案时也没有拆开玩具鸟)当然,老爱是伟大的理论物理学家,咱只是个小Coder,没法比,只是好奇罢了。
扯远了,回到正题。可以通过以下测试来验证remove是否通过equals方法来判断的
private List<INT> INTs = new ArrayList<INT>();
public void testListINT()
{
System.out.println("-----testListINT-----");
INTs.add(new INT(1));
INTs.add(new INT(2));
INTs.remove(new INT(1));
INTs.remove(new INT(2));
System.out.println("size="+INTs.size());
System.out.println("=====END=====");
}
class INT
{
public int i;
public INT(int i) {
this.i = i;
}
}
输出结果为:
-----testListINT-----
size=2
=====END=====
Object的equals方法,对于不同的对象返回的是false。在INT中override equals方法:
private List<INT> INTs = new ArrayList<INT>();
public void testListINT()
{
System.out.println("-----testListINT-----");
INTs.add(new INT(1));
INTs.add(new INT(2));
INTs.remove(new INT(1));
INTs.remove(new INT(2));
System.out.println("size="+INTs.size());
System.out.println("=====END=====");
}
class INT
{
public int i;
public INT(int i) {
this.i = i;
}
public boolean equals(Object arg0) {
if(arg0 instanceof INT){
if(((INT)arg0).i == i)
return true;
}
return false;
}
}
输出结果为:
-----testListINT-----
size=0
=====END=====
所以说,remove方法还是通过equals方法来判断指定的对象是否与列表中的对象相同。
《Effective Java》一书中还提到:
“在每个改写了equals方法的类中,你必须也要改写hashCode方法。如果不这样的话,就会违反Object.hashCode的通用约定,从而导致该类无法与所有基于hash的集合类结合在一起正常运作”
“相等的对象必须具有相等的hash code”
为了验证,再添加以下代码:
public void testMapINT()
{
System.out.println("-----testMapINT-----");
INTmap.put(new INT(1), "1");
INTmap.put(new INT(2), "2");
INTmap.remove(new INT(1));
INTmap.remove(new INT(2));
System.out.println("size="+INTmap.size());
System.out.println("=====END=====");
}
输出为:
-----testMapINT-----
size=2
=====END=====
而在INT中override hashCode方法之后:
class INT
{
public int i;
public INT(int i) {
this.i = i;
}
public boolean equals(Object arg0) {
if(arg0 instanceof INT){
if(((INT)arg0).i == i)
return true;
}
return false;
}
public int hashCode() {
return i;
}
}
输出为:
-----testMapINT-----
size=0
=====END=====
总结本文,List中,通过equals方法来判断元素是否相同;Hash类型的Collection子类,如:HashMap等是通过hashCode的返回值来标示Key值。
分享到:
相关推荐
2015 Oracle 技术嘉年华(OTN)分会场12乔晓阳 - 一个直方图问题引发的思考
从食品安全问题引发的思考.doc
对非典所引发法律问题的思考.docx
近年食品安全问题引起的思考.doc
幼儿园食品安全问题引起的思考.docx
食品安全问题引起的思考和建议.doc
运营商系统运维人员使用drop分区进行历史数据清理引起了一次性能问题,本文对此进行了具体的分析和思考。
食品安全问题引发对幼儿道德教育的思考.pdf
本书分析了程序员解决问题的方法,并且教授你其他图书所忽略的一种能力,即如何像程序员一样思考。 全书分为8章。第1章通对几个经典的算法问题切入,概括了问题解决的基本技巧和步骤。第2章通过实际编写c++代码来...
人才流动引发的人事档案管理相关问题思考.docx
094-416-对城际铁路穿越城市边缘地区引发问题的思考-word资料.pdf
chatgpt作为现象级产品受到广泛关注,本文从数据的数量、质量、驱动和保护4个方面,通过阐述chatgpt的数据特点,引发中医智能诊断研究中数据问题的思考。中医智能诊断研究需要建立数据共享模式和中医诊断的数据元标准,...
XXXX年从一起抗诉案的审理引起的对相关问题的思考(可编辑).pdf
强化问题探究促进“深度学习”发展核心素养——由一道“解三角形”试题的探究教学引发的思考.pdf
本书分析了程序员解决问题的方法,并且教授你其他图书所忽略的一种能力,即如何像程序员一样思考。 全书分为8章。第i章通对几个经典的算法问题切入,概括了问题解决的基本技巧和步骤。第2章通过实际编写C++代码来...
主要是关于Servlet模拟网上售票问题,引发的线程安全问题的思考,感兴趣的小伙伴们可以参考一下
一篇《奥康报》文章引发的大数据思考,文章围绕的问题 1、奥康凭借何种优势打败 国内外众多品牌让“亚洲”男神金秀贤代言奥康? 2、而金秀贤又为何钟爱奥康鞋?
通过供热管网故障调查数据分析,引发对管网设计、材料、施工及运行管理方面的思考,提出了供热管网安全问题的重要性。
从中药注射剂说明书思考用药安全性问题中药注射剂超剂量使用引发后果及原因概述.pdf