去除List集合中的重复元素? 如果没有Set集合,List集合是怎么去除重复元素的(字符串类型,自定义类型)?

 关键字: 如果没有Set集合,List集合是怎么去除重复元素的(字符串类型)?
 * 
 *     思考: List就可以存储重复元素,那么需求中容器中的元素必须保证唯一性,该如何解决呢??
 *    
 *   去除List集合中的重复元素? 
 *    
 *    思路:
 *
 *    1.首先我需要另一个临时容器tempList,用来存放我认为应该保留的元素.(也就是不重复的元素)
 *    2.然后我们应该遍历原容器, 一个一个的取出元素, 放入tempList.
 *    当tempList里已经装有刚刚取出的元素时,就不要往里放了,
 *    再继续取下一个元素对比,
 *    3.最后都装完了,我们可以把tempList返回给调用者.
 *    或者如果调用者希望的结果时还用原来的容器,那么我们
 *    也可以清空原来的容器,把tempList的东西都放入到原来容器中.
 *
 *    具体步骤:
 *    1.首先定义一个List集合,至于集合的实现类ArrayList不是我们本题关心的,可以换成其他的实现类也无所谓
 *    ,因为我们的案例,是关心List集合的特点.
 *    List arrayList = new ArrayList();
 *    list.add(....);
 *    list.add(....);
 *    
 *    2.定义一个方法        
 *    delRepeatElements(list)
 *    小技巧: 写完方法,在返回结果时,发现当初忘了把这个方法封装起来,好的,有解决办法
    1.全部选中要封装的内容
    2.ALT+SHIFT+M / 鼠标右键Refactor ---> extrac Method
方法中:
 *    1.定义个一个tempList用来存放临时元素
 *    List tempList = new ArrayList();
 *    
 *    2.Iterator 遍历 arrayList 中的元素(注意下面有for的写法,以及同while的区别)
 *     取出后用Obeject obj接收. 
 *     进行if判断,若果不包含 !contans(obj);
 *     不包含就加入tempList.
 *    3.根据需求,返回tempList作为结果,
 *        或者不返回结果,清空原集,将tempList中的元素复制回原集合.
 *    (这里使用了不返回结果,注释掉了返回结果的部分)
 *
 *结论:
 *1.学习框架体系时,参阅顶层,使用底层.因为这题是要针对List集合的特点,进行推倒,找出弊端.
 *因为List集合可存放重复元素,那用户需求偏偏是不需要有重复元素,用List集合怎么解决,所以
 *无需关注new 出来的对象是什么类型,只要是能创建实例的实现类都可以,LinkedList还是ArrayList.
 *2.List在存入元素时,是以Object的形式存入的,并不是String类型,这中间编译器有一个向上造型的过程.
 *同样的,当迭代器从集合中取元素时,取出来的自然也是Object类型了.
 *那么这样做就有几个问题: 
 *1.我想使用我存入对象String类型特有的功能时,就需要强转.需要Object向下转型这个过程.麻烦!
 *这个问题有没有办法解决呢?  后续我学到了泛型,解决了此问题.关于泛型知识点,详见泛型习题.
 *2.我往集合中存入一个不是String类型的对象,比如Integer,或者我自定义的对象,比如Dog,Person...
 *集合也收了我的对象,并且编译运行也没出错.我觉得这会给程序带来不稳定的因素,就算每出错,同一个集合中
 *出现不同的类型的对象,也会在运行时出现不可预知的异常等.这个问题同样泛型中解决,详见泛型习题.
 *3.重复元素去除了,但是仅仅是这种小需求,需要这么多步骤,复杂,麻烦....
 *这个问题就是为什么有Set集合出现的必要了.
 *
 */
public class ListToRepeat {

    public static void main(String[] args) {
        //1.首先定义一个List集合,至于集合的实现类选择ArrayList,因为我们的案例要求是将List集合中重复的元素删除,
        //而ArrayList是可以方重复元素的, 将集合中填入重复元素若干个.
        List arraylist = new ArrayList();
        arraylist.add("abc");    //注意点: 此时存入的"abd"并非String类型,而是Object类型
        arraylist.add("abc");    //Object obj = "abc"; 这是一个向上造型的过程
        arraylist.add("abcc");
        arraylist.add("abcc");
        arraylist.add("sdcc");
        arraylist.add("abcc");
//        arraylist.add(new Dog());    //总结3中的问题.

        /* 写完方法,在返回结果时,发现当初忘了把这个方法封装起来,好的,有解决办法
         * 1.全部选中要封装的内容
         * 2.ALT+SHIFT+M / 鼠标右键Refactor ---> extrac Method
         * */
        /*arraylist = */delRepeatElements(arraylist);

        for(Iterator it = arraylist.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
    }

    public static void delRepeatElements(List list) {
        //1.定义个一个tempList用来存放临时元素
        List tempList = new ArrayList();

        //2.遍历原容器  迭代器的用法及注意事项
        /*
        然后我们应该一个一个的取出元素,放入tempList.当tempList里已经装有刚刚取出的元素时,就不要往里放了,
        再继续取下一个元素对比,这个过程,我想到了迭代器来做.
        */
        for(Iterator it = list.iterator() ; it.hasNext();){
        /*    这是一种书写方式,java建议用这种方式迭代,而不是while.
         *     两者的区别: for循环完毕后,Iterator对象就被堆内存释放了.
         *               while循环结束后,Iterator对象还继续存在于内存当中.
         * */
            /*取出每一个元素(因为存入时以Object类型存入,取出时自然还是Object类型,需要向下转型)
             *本案不用
            String str = (String)it.next();*/

            Object obj = it.next();
            /*注意: 因为我们并没有用String对象的特有功能,所以此处
                      没有进行上面注释里的强转步骤.*/

            //判断tempList中是否包含有取出来的这个元素? 如果不包含,则存入tempList
            if(!(tempList.contains(obj))){    //如果不包含
                tempList.add(obj);    //添加到tempList容器。
            }

        }
        //4,遍历结束后,tempList容器中存储的就是唯一性的元素。可以返回给调用者
        //return tempList;

        /*5.如果调用者需要将这些唯一性的元素保留到原容器中,只要将原容器清空,
            将临时容器中的元素添加到原容器中即可。*/

        //清空原来容器
        list.clear();

        //把临时容器中的元素添加到原容器中。
        list.addAll(tempList);
    }

}
View Code

如果没有Set集合,List集合是怎么去除重复元素的(自定义类型)

/**    关键字: 如果没有Set集合,List集合是怎么去除重复元素的(自定义类型)?
 *     
 *     关于去除重复元素的题目的加深思考: (需求变成要求去除相同的自定义类型元素)
 *     同去除字符串类型相同的是,我们都要进行遍历,判断是否包含相同元素.
 *     这里需要注意的是,相同的自定义类型元素基于对象.equals方法定义的规则之上的,也就是说,
 *     如果我们我没有定义自定义类型对象的equals方法,那么这里的包含,就没有意义,因为只要是new 新对象,
 *     地址就会不同,也就是说: 本案例中语句 ----tempList.contain(obj)的结果会始终为false;
 *     
 *     思路:
 *     1.String类可contains判断的依据是String重写了equals方法的,那么同理,我们也要重写自定义类
 *     equals方法即可解决问题.

 */
public class ListToRepeat2 {

    public static void main(String[] args) {
        //1.首先定义一个List集合,存储自定义类型,这里我们新建Dog类描述狗的类

        List doglist = new ArrayList();
        doglist.add(new Dog("大宝","杜宾",5));    
        doglist.add(new Dog("小黄","金毛犬",7));    
        doglist.add(new Dog("铁球","阿拉斯加",2));    
        doglist.add(new Dog("大宝","萨摩耶",1));    
        doglist.add(new Person("小孩",5));        //结论2的问题.
        doglist.add(new Dog("大宝","萨摩耶",1));    //重复需要去除
        doglist.add(new Dog("小黄","金毛犬",7));    //重复需要去除

        //删除重复元素的方法
        delRepeatElements(doglist);

        //遍历,输出doglist
        for(Iterator it = doglist.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
        /* 输出结果:
         狗 [名字:大宝, 犬种=杜宾, 年龄=5]
         狗 [名字:小黄, 犬种=金毛犬, 年龄=7]
         狗 [名字:铁球, 犬种=阿拉斯加, 年龄=2]
         狗 [名字:大宝, 犬种=萨摩耶, 年龄=1]
         人类 [name=小孩, age=5] 
         */
        /*结论:
         *1.学习框架体系时,参阅顶层,使用底层.因为这题是要针对List集合的特点,进行推倒,找出弊端.
         *因为List集合可存放重复元素,那用户需求偏偏是不需要有重复元素,用List集合怎么解决,所以
         *无需关注new 出来的对象是什么类型,只要是能创建实例的实现类都可以,LinkedList还是ArrayList.
         *2.List在存入元素时,是以Object的形式存入的,并不是String类型,这中间编译器有一个向上造型的过程.
         *同样的,当迭代器从集合中取元素时,取出来的自然也是Object类型了.
         *那么这样做就有几个问题: 
         *1.我想使用我存入对象String类型特有的功能时,就需要强转.需要Object向下转型这个过程.麻烦!
         *这个问题有没有办法解决呢?  后续我学到了泛型,解决了此问题.关于泛型知识点,详见泛型习题.
         *2.我往集合中存入一个不是String类型的对象,比如Integer,或者我自定义的对象,比如Dog,Person...
         *集合也收了我的对象,并且编译运行也没出错.我觉得这会给程序带来不稳定的因素,就算每出错,同一个集合中
         *出现不同的类型的对象,也会在运行时出现不可预知的异常等.这个问题同样泛型中解决,详见泛型习题.
         *3.重复元素去除了,但是仅仅是这种小需求,需要这么多步骤,复杂,麻烦....
         *这个问题就是为什么有Set集合出现的必要了.*/
    }

    public static void delRepeatElements(List list) {
        //1.定义个一个tempList用来存放临时元素
        List tempList = new ArrayList();

        //2.遍历原容器  
        for(Iterator it = list.iterator() ; it.hasNext();){
            Object obj = it.next();

            //判断tempList中是否包含有取出来的这个元素? 如果不包含,则存入tempList
            //这里需要重写Dog类的equals方法
            if(!(tempList.contains(obj))){    //如果不包含
                tempList.add(obj);    //添加到tempList容器。
            }
        }
        //4,遍历结束后,tempList容器中存储的就是唯一性的元素。可以返回给调用者
        //return tempList;

        /*5.如果调用者需要将这些唯一性的元素保留到原容器中,只要将原容器清空,
            将临时容器中的元素添加到原容器中即可。*/

        //清空原来容器
        list.clear();

        //把临时容器中的元素添加到原容器中。
        list.addAll(tempList);
    }
}

描述狗的类

/**
 *    描述狗的类
 */
public class Dog {

    private String name;
    private String type;
    private int age;

    public Dog(String name, String type, int age) {
        super();
        this.name = name;
        this.type = type;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "狗 [名字:" + name + ", 犬种=" + type + ", 年龄=" + age + "]";
    }


    /* 
     * 重写equals方法
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Dog other = (Dog) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (type == null) {
            if (other.type != null)
                return false;
        } else if (!type.equals(other.type))
            return false;
        return true;
    }
}
描述人的类

public class Person {
    private String name;
    private int age;
    @Override
    public String toString() {
        return "人类 [name=" + name + ", age=" + age + "]";
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}
View Code

 

posted @ 2016-05-02 18:00  安仔80  阅读(2512)  评论(0编辑  收藏  举报