这个问题,自己在平时中并未遇见,但是有人问了这个问题后,自己加以思考,整理出来自己的思路来解答,并看了底层的代码加以证明。现在和大家分享下,本人只是抛砖引玉,希望能和更多热爱技术的猿猿一起思考探索下技术。欢迎拍砖,发表不同的想法,也欢迎有猿猿对底层这些实现思维交流交流。如果是我们自己设计这些东西,我们会不会有更好的逻辑去实现,如果没有,它这种底层实现为什么好?
下面进入主餐:
我整理下这位提问人的问题:
就是List容器中添加一个new出来的对象,然后为什么在remove点一个新构造出来的一摸一样的对象,总是不能成功remove掉它。
具体问题代码如下:
[code]
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());
}
}
[/code]
我看到这个问题后的理解是:
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)
[code]
public boolean remove(Object obj)
{
return map.remove(obj) == PRESENT;//这里的map.remove指向2的remove
}
[/code]
2. java.util.HashMap
[code]
public Object remove(Object obj)
{
Entry entry = removeEntryForKey(obj);//这里的removeEntryForKey方法来源于3
return entry != null ? entry.value : null;
}
[/code]
3.java.util.HashMap
[code]
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;
}
[/code]