去除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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。