您的位置:首页 > 编程语言 > Java开发

关于Java中的List容器的remove注意细节

2012-09-15 00:52 405 查看
第一次发布地址:http://258516630.ddjava.com/blog/blog.html?blogId=437

这个问题,自己在平时中并未遇见,但是有人问了这个问题后,自己加以思考,整理出来自己的思路来解答,并看了底层的代码加以证明。现在和大家分享下,本人只是抛砖引玉,希望能和更多热爱技术的猿猿一起思考探索下技术。欢迎拍砖,发表不同的想法,也欢迎有猿猿对底层这些实现思维交流交流。如果是我们自己设计这些东西,我们会不会有更好的逻辑去实现,如果没有,它这种底层实现为什么好?

下面进入主餐:

我整理下这位提问人的问题:

就是List容器中添加一个new出来的对象,然后为什么在remove点一个新构造出来的一摸一样的对象,总是不能成功remove掉它。

具体问题代码如下:

package javaFile;

public class Name {

private String fistName ,lastName;//fiseName姓 lastName名

Name(String fistName ,String lastName){

this.fistName =fistName;

this.lastName=lastName;

}

public String getfistName(){

return fistName;

}

public String getlastName(){

return lastName;

}

public String getToString(){

return fistName + lastName;

}

//重写equals的方法

public boolean equalse(Object obj){

if(obj instanceof Name){//如果这个boj输入这个Name对象

Name name =(Name)obj ;

return (fistName.equals(name.fistName))

&& (lastName.equals(name.lastName));

}

return super.equals(obj);

}

public int hashCoed(){

return fistName.hashCode();

}

package javaFile;

import java.rmi.Naming;

import java.util.*;

public class Testconllenction {

public static void main(String[] args) {

Collection c = new HashSet();//new 一个ArrayListd对象其实是父类指向子类对象

//想list里面放东西

//Name a = new Name("f","ff");

c.add("Hello");

c.add(new String("fafas"));

c.add(new Name("f1" ,"f2"));

c.add(new Integer(100));

c.remove(new String("fafas"));//除非是内部类才可以删除否则要进行equals对比

c.remove(new Name("f1" ,"f2"));//问题在这里啊看清粗啊运行的时候?????????????????????????

c.remove(new Integer(100) );

c.remove("Hello");//remove 是删除的意思

System.out.println(c.remove(new Name("f1","f2")));//false 去不掉

//原因 :没有重写equals 方法 比较两个对像是否相等是要重写equals的方法

// 在用到Map 里面进行对比会用hashCored进行对比原因是效率更高

System.out.println(c.size());

System.out.println(c);

//System.out.println(a.toString());

}

}


我看到这个问题后的理解是:

1.list容器中add方法中的对象的内存地址是为aaaa(假定,可以是任意的内存地址值),但是remove方法中的对象,虽然是和add方法中的对象值是一样的,看起来是一个同一个对象,但其实它们是不同的对象。

举个通俗易懂的现实例子来说明吧。

一、在一个小区里,2号楼202室的房间布局、家具以及住的人是和3号楼202室一模一样的,但是这两个房屋的地址是不一样,所以它们是不同的房子。

二、当你聘请拆迁队要拆迁掉你在2号楼202室的房子,你带他去3号楼202室的房屋,它肯定不会拆的,它会给你报提示,这不是你要求我们要拆的房子。

三、因为名单上的地址和带到拆除房屋的地址不相同。

类比:

①拆迁队==List容器

②2号楼202室 == add方法里new出来的对对象

③add(new Objeact()) == 给它2号楼202室的地址的房子

④3号楼202室 == remove方法里new出来的对象

⑤remove(new Object()) == 带它去的3号楼202室的地址的房子

这是我能最快想到一个能用类似的实际例子说明的。可能,现实中拆迁队不会这么迂腐,但是机器就是这么忠贞不二的去执行既定的规则。如果非要和我争论拆迁队肯定二话不说拆除3号楼202室的房子的同学轻绕道,谢谢。

以下是我看java提供的底层代码,来佐证我的理解:

1. java.util.HashSet

HashSet.remove(Object o)

public boolean remove(Object obj)

{

return map.remove(obj) == PRESENT;//这里的map.remove指向2的remove

}


2. java.util.HashMap

public Object remove(Object obj)

{

Entry entry = removeEntryForKey(obj);//这里的removeEntryForKey方法来源于3

return entry != null ? entry.value : null;

}


3.java.util.HashMap

final Entry removeEntryForKey(Object obj)

{

int i = obj != null ? hash(obj.hashCode()) : 0;//关键地方

int j = indexFor(i, table.length);

Entry entry = table[j];

Entry entry1;

Entry entry2;

for(entry1 = entry; entry1 != null; entry1 = entry2)

{

entry2 = entry1.next;

Object obj1;

if(entry1.hash == i && ((obj1 = entry1.key) == obj || obj != null && obj.equals(obj1)))

{

modCount++;

size--;

if(entry == entry1)

table[j] = entry2;

else

entry.next = entry2;

entry1.recordRemoval(this);

return entry1;

}

entry = entry1;

}

return entry1;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: