黑马程序员技术交流社区
标题:
为什么remove会依赖元素中的equals方法
[打印本页]
作者:
雷楚光
时间:
2012-2-21 19:10
标题:
为什么remove会依赖元素中的equals方法
这段代码看不懂,为什么结果是ture啊。主要不懂的是:remove方法底层也是依赖于元素的equals方法。什么意思?
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
public boolean equals(Object obj)
{
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age;
}
}
class ArrayListTest
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();
al.add(new Person("lisi03",33));
sop(al.remove(new Person("lisi03",33)));
//remove方法底层也是依赖于元素的equals方法。
}
}
作者:
李晓俊老师
时间:
2012-2-21 19:38
如果是判断集合是否包含某个对象元素,即contians方法的底层就调用对象equals的方法进行比较的,,这点你应该知道;;
其实集合在删除一个对象元素时是先判断是否有该元素,,它将该元素和自己的所有元素用equals都比较了一下,,才判断的,
如果有就删除成功,返回true,,反之返回false..对于基本数据类型的集合,,不需要重写equals方法,,因为他们能根据ASCII码表进行
比较,直接返回的就是比较后的结果,,,不过对于更复杂的对象元素,,,如Person,它包含name和age属性,,所以不能按照默认的equals
进行判断,我们必须重写equals方法,,,return this.name.equals(p.name) && this.age == p.age;
这句就是判断两个Person对象的,,如果name和age都相同就返回true,,反之返回false
作者:
吴璞玉
时间:
2012-2-21 19:48
remove方法是移除此列中首次出现的指定元素(如果它存在的话)
确切的说是移除满足(obj==null?get(i):obj.equals(get(i)))的最低索引的元素
底层是依靠equals方法来判断你所要移除的元素是否在列表中存在,而结果返回时true是因为remove方法的返回值为boolean类型,返回true代表此列表包含指定的元素。
作者:
H07000223
时间:
2012-2-21 19:52
本帖最后由 H07000223 于 2012-2-21 19:58 编辑
对于这段代码,说说自己的理解吧
我认为,注释说的
remove方法底层也是依赖于元素的equals方法
应该是有道理的:
1.首先person类中重写了父类Object的equals方法,也就是说如果两个person实例的name和age属性相等的话,他们就是同一个对象,也就是内存地址相同。
2.然后当ArrayList中添加一个person类型元素,生成了一个新的person对象,开辟了一个新的内存空间。
3.调用ArrayList的remove方法,按照常理第二次
new
也会生成新的person对象,返回一个false。但是Person类重写了equals判断方法。
由于两次
new
的person对象的name和age一模一样,所以其实会指向同一个内存地址,两者其实是一回事。
我估计每次
new
一个对象,都会自动调用当前类的equals方法,看看是否已经存在该对象了,有了的话还生成干吗,没有的话自然生成一个新的
4.我想你也可以通过得到的结果反过来理解:
remove方法返回true就是说成功删除了该元素
->
也就是说两次
new
的是同一个对象
->
生成对象会自动调用equals方法进行是否存在的判断
作者:
唐溪永
时间:
2012-2-21 21:03
这是一个经典检查Remove与Equals 的方法
例子代码
static void Main(string[] args)
{
List<A> list = new List<A>();
list.Add(new A(1, 1));
list.Add(new A(2, 2));
Console.WriteLine(list.Count);
list.Remove(new A(1, 1));
Console.WriteLine(list.Count);
}
复制代码
其实代码很简单,建立一个链表,增加2个元素,然后试图删除一个元素。在删除前后打印出链表中元素的个数.
然而结果却是:不一定!
问题的关键就是
list.Remove(new A(1, 1));
看似这句的企图是,删除第一个元素,那么它能达到这个目的吗?这要看看,list.Remove(T)的实现原理了,首先要检查链表中是否有这个元素,然后才能删除。那么,怎么确定是否有这个元素呢?
此方法使用用于 T(列表中的值的类型)的默认相等比较器 EqualityComparer(T).Default 来确定相等性。
那么我们看看这个EqualityComparer(T).Default 是什么?
返回一个默认的相等比较器,用于比较此泛型参数指定的类型。
Default 属性检查类型 T 是否实现此 System.IEquatable(T) 泛型接口,如果实现,该属性将返回一个使用该实现的 EqualityComparer(T)。否则,它返回一个使用 T 提供的 Object.Equals 和 Object.GetHashCode 的重写的 EqualityComparer(T)。
判断相等并不简单,如果什么都不做的话,默认会使用Object.Equals()函数判断相等。而我们知道Object.Equals()其实实现的是同一性比较,而不是相等性比较。所以只有两个引用变量指向同一个对象,才判定为相等。然而上述代码中,显然new A(1,1)返回的引用变量不可能指向链表中引用变量指向的对象,所以输出结果会是:
2
2
然而,如果我们的A,覆盖了Object的Equals函数,例如:
class A
{
public int x;
public int y;
public A(int _x, int _y)
{
x = _x;
y = _y;
}
public static bool operator == (A a1, A a2)
{
Console.WriteLine("operator ==");
return (a1 == a2);
}
public static bool operator != (A a1, A a2)
{
return (a1 != a2);
}
public override bool Equals(object obj)
{
Console.WriteLine("override Equals");
if (this.x == ((A)obj).x && this.y == ((A)obj).y)
return true;
else
return false;
}
}
复制代码
那么输出结果将会是
2
1
所以,list.Remove(T)完全依赖于T的实现。上述代码也证明了,List.Remove(T)不会使用T的==操作符而是使用T的Equals()方法判断相等性。
希望以上会有帮助
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2