黑马程序员技术交流社区

标题: ArryList练习中,遇到的问题 [打印本页]

作者: fufeng    时间: 2014-4-15 10:49
标题: ArryList练习中,遇到的问题
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;

                System.out.println(this.name+"======="+p.name);

                return this.name.equals(p.name) && this.age == p.age;     
        }

        public String getName()
        {
                return name;
        }
        public int getAge()
        {
                return age;
        }

}
class  Noname9
{
        public static void main(String[] args)
        {
                ArrayList al = new ArrayList();

                al.add(new Person("zhangsan01",31));
                al.add(new Person("zhangsan01",31));
                al.add(new Person("zhangsan03",32));
                al.add(new Person("zhangsan05",34));
                al.add(new Person("zhangsan05",34));

                Iterator it = al.iterator();
        while(it.hasNext())
                {
                        Person p = (Person) it.next();
                        sop("name: "+p.getName()+"--"+"age: "+p.getAge());
                }

        }
        public static void sop(Object obj)
        {
                System.out.println(obj);
        }
}
要实现的功能为:当向ArrayList中添加Person对象的时候,调用Person类中的equals方法,将name和age一样的对象,认为是相同的对象,在ArrayList只存储一个,保证里面没有重复对象,
但是结果却是
全部都添加进出了
这是为什么呢?
作者: TTc    时间: 2014-4-15 11:12
ArraryList特点:底层实现数据结构是数组结构,查询效率高,增删效率低,且因为其存在角标,是有序的,所以可以储存相同的对象,其存入的地址(角标)不同。
作者: 759345779    时间: 2014-4-15 11:21
list集合的特点是有有序的,每次添加等于是从下一新的角标开始,存储不会自动调用equals比较内容的,其存储内容可以指向同一对象,或者具有相同内容的不同对象
比如下面代码
  1. ArrayList al = new ArrayList();
  2. Person per = new Person("zhangsan05",34);
  3.              al.add(per);
  4.              al.add(per);
  5.              al.add(per);
  6.              al.add(per);
  7.              al.add(per);
复制代码

添加了5次,都是同一对象,
打印结果是:
name: zhangsan05--age: 34
name: zhangsan05--age: 34
name: zhangsan05--age: 34
name: zhangsan05--age: 34
name: zhangsan05--age: 34

作者: 曹冬明    时间: 2014-4-15 11:27
ArrayList里是可以有重复元素的,所以你的equals方法不会调用,如果是其他集合就会调用了,因为其他集合元素必须唯一
作者: 宋超2356    时间: 2014-4-15 11:34
这样才是正常的啊,因为List本来就是不会自动调用equals方法的,它都是存于新的脚标下,所以重写是没意义的,估计是和Set弄混了
付Set的添加方法,过去写的博客....
  1. import java.util.*;

  2. public class Test
  3. {
  4.     public static void main(String[] args)
  5.     {
  6.         HashSet hs = new HashSet();
  7.         hs.add(new  Smile("呵呵"));
  8.         hs.add(new  Smile("呵呵"));
  9.         System.out.println(hs);
  10.         System.out.println("------分割线------");
  11.       
  12.         Smile s=new Smile("嘿嘿");
  13.         hs.add(s);
  14.         hs.add(s);
  15.         System.out.println(hs);
  16.         System.out.println("======分割线======");//Smile继承object的hashCode和equals方法
  17.       
  18.         String s1 = new String("哈哈");
  19.         String s2 = new String("哈");
  20.         hs.add(s1);
  21.         hs.add(s2);
  22.         System.out.println(hs);//String类重写过hashCode与equals所以就不同于Smile,不能添加相同的
  23.         
  24.     }
  25.    
  26. }

  27. class Smile
  28. {
  29.     String name;
  30.     Smile(String name)
  31.     {
  32.         this.name=name;
  33.     }
  34.     public String toString() {
  35.     return name;
  36.     }
  37. }


  38. 输出结果是:[呵呵, 呵呵]
  39. ------分割线------
  40. [呵呵, 呵呵, 嘿嘿]
  41. ======分割线======
  42. [哈哈, 呵呵, 呵呵, 嘿嘿]
复制代码

作者: 也许依然    时间: 2014-4-15 12:17
|--List : 元素是有序的,元素可以重复。因为该集合体系有索引
                |--ArrayList: 底层的数据结构使用的是数组结构。 线程不同步
                |--LinkedList: 底层的数据结构使用的是链表结构
                |--Vector: 底层是数组数据结构。 线程同步。被ArrayList替代了
        |--Set  :元素是无序,元素不可以重复
                |--HashSet:数据结构是哈希表,线程时非同步的
                                        保证元素唯一性的原理:判断hashCode值是否相同,如果相同继续判断equals方法,是否为true
                |--TreeSet:可以对Set集合中的元素进行排序,底层数据结构是二叉树
                                        保证元素唯一性的依据:compareTo方法返回值是否为0
                                       
                                        TreeSet集合的第一种排序方式:让元素自身具备比较性
                                                元素需要实现Comparable接口,覆盖compareTo方法,这种方式称为元素的自然顺序
                                        TreeSet集合的第二种排序方式:当元素自身不具备比较性,或者具备的比较性不是所需要的
                                                这时需要让容器自身具备比较性
                                                定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数


ArrayList集合中可以存储相同的元素,在存储中不会判断equals方法,按下标的顺序依次存入,如果要存入不同的元素,需要使用Set集合,覆盖hashCode方法,equals方法,并实现Comparable接口覆盖compareTo方法

代码演示:
  1. public class Set {
  2.         public static void main(String[] args){
  3.                 TreeSet<Person> ts = new TreeSet<Person>();
  4.                 ts.add(new Person("lisi01",11));
  5.                 ts.add(new Person("lisi02",12));
  6.                 ts.add(new Person("lisi01",13));
  7.                 ts.add(new Person("lisi04",11));
  8.                
  9.                 Iterator<Person> it = ts.iterator();
  10.                 while(it.hasNext()){
  11.                         Person p = it.next();
  12.                         System.out.println(p);
  13.                 }
  14.         }
  15. }

  16. class Person implements Comparable<Person>{
  17.         private int age;
  18.         private String name;
  19.         Person(String name,int age){
  20.                 this.name = name;
  21.                 this.age = age;
  22.         }
  23.        
  24.         @Override
  25.         public int compareTo(Person p){
  26.                 int num = new Integer(this.age).compareTo(new Integer(p.age));
  27.                 if(num==0)
  28.                         return this.name.compareTo(p.name);
  29.                 return num;
  30.         }
  31.        
  32.         @Override
  33.         public int hashCode(){
  34.                 return name.hashCode()+age*39;
  35.         }
  36.        
  37.         @Override
  38.         public boolean equals(Object obj){
  39.                 if(obj instanceof Person)
  40.                         throw new RuntimeException("error");
  41.                 Person p = (Person)obj;
  42.                 return name.equals(p.name) && age==p.age;
  43.         }
  44.        
  45.         public int getAge(){
  46.                 return age;
  47.         }
  48.        
  49.         public void setAge(int age){
  50.                 this.age = age;
  51.         }
  52.        
  53.         public String getName(){
  54.                 return name;
  55.         }
  56.        
  57.         public void setName(String name){
  58.                 this.name = name;
  59.         }
  60.        
  61.         @Override
  62.         public String toString(){
  63.                 return age+" "+name;
  64.         }
  65. }
复制代码


作者: 491138002    时间: 2014-4-15 12:42
ArrayList里是可以有重复元素的,可以通过HashSet剔除
    // 删除ArrayList中重复元素
    public static void removeDuplicateBySet(List list) {
          HashSet h = new HashSet(list);
          list.clear();
          list.addAll(h);
          System.out.println(list);
    }
作者: shi0000    时间: 2014-4-15 12:44
本帖最后由 shi0000 于 2014-4-15 12:50 编辑

看系统调用什么方法,就看集合是什么结构,如:  数组结构的是系统使用a【i】=“”来存储到栈中,  底层是二叉树是,系统会调用hashcode()和equals()方法,先赋给他一个hash值,再比较其大小,最后按照二叉树的形式保存起来。

  底层是hash表时,系统也是会有hashcode()和equals()方法,先赋hash值,再比较hash是否相等,当相等时,就会将新进来的对象存入,
覆盖掉原来的对象。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2