A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 朝哥 中级黑马   /  2012-6-2 12:14  /  3162 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

package cn.itcast;

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)
        {
                if(!(obj instanceof Person))
                        return false;
                Person p = (Person)obj;
                return this.name.equals(p.name) && this.age == p.age;
        }
       
}
class ArrayListTest2
{
        public static void main(String[] args)
        {
                ArrayList al = new ArrayList();

                al.add(new Person("lisi02",32));
                al.add(new Person("lisi02",32));

                al = singleElement(al);
               
                System.out.println(al);
        }

        //自定义的去除集合中重复的对象。
        public static ArrayList singleElement(ArrayList al)
        {
                ArrayList newAl = new ArrayList();
                Iterator it = al.iterator();
                while(it.hasNext())
                {
                        Object obj = it.next();
                        if(!newAl.contains(obj))
                                newAl.add(obj);
                }
                return newAl;
        }
}

困扰我的问题:自定义一个可以取出集合中重复对象的功能singleElement,它里面判断的是对象的地址值。
我知道Person类里面有个equals,我们复写了他的方法,改为自己定义的:只要name和age相同,就是一个对象。
问题来了。
他是怎么做到比两个对象的地址值的。难道是在创建第二个对象时,默认直接p2指向p1对象地址值?

评分

参与人数 1技术分 +1 收起 理由
袁錦泰 + 1

查看全部评分

11 个回复

倒序浏览
你创建ArrayList对象时,这对象中已经封装好了比较方法,是内部调用的,你可以查看jdk中原代码看它是怎么比较的。
这都是封装好的。
回复 使用道具 举报
兄弟,这个是API里面关于contains的定义:
boolean contains(Object o)如果此 collection 包含指定的元素,则返回 true。更确切地讲,当且仅当此 collection 至少包含一个满足 (o==null ? e==null : o.equals(e)) 的元素 e 时,返回 true。
标红色部分说明contains调用的还是底层的equals方法,你复写了方法equals方法,所以contains是按照你复写的方法比较的,并不是比较地址值~
所以说这句话“自定义一个可以取出集合中重复对象的功能singleElement,它里面判断的是对象的地址值。”是有误的

评分

参与人数 1技术分 +1 收起 理由
袁錦泰 + 1

查看全部评分

回复 使用道具 举报
我再把问题简单一下
创建俩Person对象,如果没有Person类中复写equals方法,俩对象的地址值不一样,但是你一复写equals方法,俩地址值就会一样。
关键是我没调用equals方法啊。为什么new Person(“张三”,12) 和 new Person(“张三”,12)的地址值是一样的?
回复 使用道具 举报
黄奕豪 发表于 2012-6-2 12:31
兄弟,这个是API里面关于contains的定义:
boolean contains(Object o)如果此 collection 包含指定的元素, ...

yes,my god。明白了。真恶心,困找了很久。
狂谢之!
回复 使用道具 举报
自己定义了类  如果没有重写equals方法,那么他们的equals方法是调用object类的equals方法。object类的equals方法比较的是地址是否相同。
如果重写了equals方法 就按照自己的定义的方法比较。
回复 使用道具 举报
你好,首先:==是判断两个对象是否是同一对象,而equals()则判断两个对象的内容是否相等,你重写了equals方法,来重新定义只要name和age相等就是同一个对象。而要是同一个对象就必须比较这2个对象的引用,关于java是怎样做到2个对象的引用的比较的,的确是java已经封装好了的我也写了一段代码:
  1. 。[code]class Student {
  2.         String name;
  3.         Student(String name) {
  4.         this.name = name;
  5. }
  6. public boolean equals(Object obj) {
  7.         Student otherObj = (Student)obj;
  8.         if(obj == this) { // 如果是同一个对象,则相等
  9.         return true;
  10. }
  11.         if(otherObj.name.equals(this.name)) { //如果姓名相等,则相等
  12.         return true;
  13. }
  14.         return false; //否则,不是上面两种情况则不相等.
  15. }
  16. }

复制代码
[/code]
希望能帮到你
回复 使用道具 举报
2楼说的话,关键还是在contains方法上,里面对象与对象相比时就调用了Person类中你定义的equals方法。
回复 使用道具 举报
容器类对象在调用contains 方法时需要比较对象是否相等,就会用到对象的equals 方法和hashCode方法,你自己定义的类要重写这两个方法,来实现自定义对象的相等规则。
我将你的代码添加了这两个方法,和ToString方法,其中hashCode方法是直接调用String类重写过的。
代码如下:
  1. import java.util.*;

  2. class Person
  3. {
  4.          private String name;
  5.          private int age;
  6.          
  7.         Person(String name,int age)
  8.          {
  9.                  this.name = name;
  10.                  this.age = age;
  11.          }

  12.         //重写equals
  13.         public boolean equals(Object obj)
  14.          {
  15.                  if(obj instanceof Person){
  16.                                          Person p = (Person)obj;
  17.                                          return this.name.equals(p.name) && this.age == p.age;
  18.                                  }
  19.                  else
  20.                                          return super.equals(obj);//子类无法处理交给父类处理
  21.          }
  22.                 //重写hashCode
  23.                  public int hashCode() {

  24.                         return name.hashCode();//利用String类重写的hashCode()方法
  25.                  }
  26.                 //重写toString       
  27.                  public String toString() {

  28.                         return name + " "+ age;
  29.                  }
  30.          
  31. }

  32. class ArrayListTest2
  33. {
  34.          public static void main(String[] args)
  35.         {
  36.                  ArrayList al = new ArrayList();

  37.                                  al.add(new Person("lisi02",32));
  38.                  al.add(new Person("lisi02",32));

  39.                 al = singleElement(al);
  40.                  
  41.                 System.out.println(al);//调用了toString方法
  42.          }

  43.         //自定义的去除集合中重复的对象。
  44.          public static ArrayList singleElement(ArrayList al)
  45.          {
  46.                  ArrayList newAl = new ArrayList();
  47.                  Iterator it = al.iterator();
  48.                  while(it.hasNext())
  49.                  {
  50.                          Object obj = it.next();
  51.                          if(!newAl.contains(obj))
  52.                                  newAl.add(obj);
  53.                  }
  54.                  return newAl;
  55.                 }               
  56. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
袁錦泰 + 1

查看全部评分

回复 使用道具 举报
朝哥 发表于 2012-6-2 12:52
2楼说的话,关键还是在contains方法上,里面对象与对象相比时就调用了Person类中你定义的equals方法。 ...

不只是contains()方法会调用到equals()方法,remove()方法也是一样.视频中有讲到,可以回顾一下.
回复 使用道具 举报
袁錦泰 发表于 2012-6-2 14:18
不只是contains()方法会调用到equals()方法,remove()方法也是一样.视频中有讲到,可以回顾一下. ...

谢谢!细节很多,都要注意了。
回复 使用道具 举报
朝哥 发表于 2012-6-2 14:51
谢谢!细节很多,都要注意了。

:handshake 不必客气... 互相学习!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马