集合的總結與常見問題解析

1.如何定義Collection?java

Collection是一個集合體系的頂層接口,此接口中的方法都是:public abstract。
    能夠進行增刪改查的操做:
            增長:   -->>   boolean add(Object o)                        一次添加一個元素,元素能夠是Object 的子類,返回true
                            boolean addAll(Collection c)                一次添加一批元素,參數是Collection類型的
            刪除:   -->>   void clear()                                 清空集合
                            boolean remove(Object o)                一次刪除一個元素,成功刪除,返回true
                            boolean removeAll(Collection c)                一次刪除一批,成功,返回true
            查找:   -->>   boolean contains(Obejct o)                判斷集合中是否包含指定元素
                            boolean containsAll(Collection c)        是否包含一批
                            boolean isEmpty()                        判斷集合是否爲空
                            int size()                                獲取集合中的個數
            修改:   -->>   clear()                                        清空集合中的全部元素
            獲取:   -->>   int size()                                返回集合容器的大小
            集合轉換爲數組:
                            Object[] toArray();        該方法將集合轉爲數組,集合中的每個元素,做爲了數組一個的元素

【注意:集合中存儲的是對象的引用,而不是對象自己】
【注意:接口與接口之間屬於:繼承關係】編程

二、錄入用戶在控制檯輸入的信息,可使用Scanner類數組

Scanner sc = new Scanner();

三、List接口: ---->> public interface List extends Collection安全

List是一個繼承了Collection接口的接口,具有了比Collection多的功能。
    特色: ---->>   有序、有角標、可重複。
                    此接口的用戶能夠對List接口中每一個元素的插入位置進行精確地控制。(經過角標獲取集合中的元素)
    
    增:
            void add(int index,Object element)        指定元素添加的角標,增長一個元素
            boolean addAll(int index,Collection c)        指定位置,增長一批
    刪:
            Element remove(int index)                        刪除指定位置的元素,而且返回該元素
    改:
            Element set(int index,Object element)        替換指定位置的元素,須要肯定該元素的位置和新元素,返回就元素。
            List<E> subList(int fromIndex,int toIndex)        截取子結合,返回一個List,包含頭,不包含尾。
    查:
            Object get(int index)                        獲取List結合指定位置的元素
            int indexOf(Object o)                        返回此列表中第一次出現的指定元素的索引
            int lastIndexOf(Object o)                倒序查找指定元素的位置
                    【注意角標越界:IndexOutOfBoundException  //  找不到返回:-1】
                    【Object set = new list.get(list.size()-1);】
    【List集合特有的增刪改查方法都跟角標有關係!!!!】

【問:如何取出List集合中的元素?】網絡

經過for循環,並使用size()和set()方法可取出List集合中的每個元素。

四、ArrayList -->> 是一個List接口的實現類數據結構

具有List集合的特色:有序、有角標、可重複。
                    該類內部,維護了一個數組, 數組的元素是Object 類.
                    在ArrayList 類的構造函數中初始化的該數組, 若是沒有顯示的指定數組的長度,【默認長度是10】
                            也就是說: 使用無參數構造,new ArraList(), 自動建立的數組長度是60%.
                    ArrayList 在添加元素時,都會檢測數組是否已滿,若是滿了,自動擴容(建立一個新數組),
                            【新數組長度的是老數組的1.6倍】
                            而且將老數組中的元素拷貝到了新數組,使用新數組繼續增長元素.

五、ArrayList使用什麼實現的?其優缺點是什麼?多線程

ArrayList是使用數組實現的。
    優勢:內存地址連續,查找快;
    缺點:增長和刪除元素,須要設計數組的擴容或者拷貝,效率很低。
    ---->>   總結:  數組實現,查找快,增刪慢。
    ArrayList中的方法:
        boolean contains(Object o)    判斷集合是否包含指定的元素,涉及了元素的比較(對象的比較)
                                      內部使用了元素的equals()方法。
        String類                          重寫了equals()方法

六、LinkedList ---->> List接口的實現類,具有:有序、有角標、元素可重複的特色。【和ArrayList相似】函數

LinkedList是一個雙向鏈表,該集合提供了方便操做集合頭和集合尾的方法。
    【若是集合中沒有元素能夠獲取或者刪除,則拋:NoSuchElementException】
    LinkedList特有的方法:
            增長:
                    void addFirst(Element e)
                    void addLast(Element e)
            刪除:
                    Object getFirst()
                    Object getLast()
            查找:
                    Object removeFirst()                移除並返回此列表的第一個元素
                    Object removeLast()                移除並返回此列表的最後一個元素
    數據結構:
            堆棧:
                    void push(Element e)                將元素推入此列表所表示的堆棧
                    Element pop()                        今後列表所表示的堆棧處彈出一個元素
                   【壓棧和彈棧:先進後出,後進先出】
            隊列:
                    boolean offer(Element e)        將指定元素添加到此列表的末尾(最後一個元素)
                    Element poll()                        獲取並移除此列表的頭(第一個元素)
                    Element peek()                        獲取但不移除列表的頭(第一個元素)
                   【隊列的數據結構:先進先出】
    返回逆序的迭代器對象:
                    descendingIterator()                返回逆序的迭代器對象

七、LinkedList的實現原理是什麼?其優缺點?性能

LinkedList的實現原理是:鏈表實現,其內存地址是不連續的。
    優勢:相對於數組,增長元素快;
    缺點;因爲內存地址不連續,查找性能低。

八、集合與數組有什麼區別?測試

相同點:數組和集合都是容器
            數組和集合中存放的都是【對象的引用】而非對象自己
    不一樣點:數組存儲【基本數據類型】,是單一的。並且一旦聲明好長度後,長度不可變;
            集合【只能】儲存【對象】,可是能夠是任意類型的對象,其長度可變。

【集合的分類】

----|Iterable:接口
    Iterator iterator()
    ----|Collection:單列集合
            ----|List:        有序存儲順序,可重複
                    ----|ArrayList:        數組實現,查找快、增刪慢
                                            因爲是數組實現,在增和刪的時候會牽扯到數組增容,以及拷貝元素,因此慢;
                                            數組是能夠直接按索引查找的,因此查找時比較快。
                    ----|LinkedList:        鏈表實現,增刪快、查找慢
                                            因爲鏈表實現,增長時只要讓前一個元素記住本身就能夠了,刪除時讓前一個元
                                            素記住後一個元素,後一個元素記住前一個元素,這樣的增刪效率高;
                                            但查詢時須要一個一個的遍歷,因此效率比較低。
                    ----|Vector:                多線程安全、效率略低        【ArrayList單線程效率高,可是多線程要使用Vector】
            ----|set:        無序存儲,不可重複
                    ----|HashSet                線程不安全,存取速度快
                                            底層是以hash表實現的
                    ----|TreeSet                紅-黑樹的數據結構,默認對元素進行天然排序(String)
                    【TreeSet自身具有排序功能】
                            ----|Comparable
                                    ----|compareTo(Object o)            元素自身具有比較性
                            ----|Comparator
                                    ----|compare(Object o1,Object o2)    給容器傳入比較器
                                            若是在比較的時候兩個對象返回值是【0】,那麼這兩個元素【重複】
                            【當Comparable和Comparator比較方式同時存在時,以Comparator比較方式爲主】
                    ----|LinkedHashSet        會保存插入的順序
----|Map:  將鍵映射到值的對象。一個映射不能包含重複的鍵,每一個鍵最多隻能映射一個值。
            interface Map<K,V>        
    ----|TreeMap                底層是二叉樹數據結構,能夠對map集合中的鍵進行排序
                            須要使用Comparable或者Comparator進行比較排序。
                                    【return 0 判斷鍵的惟一性】
    ----|HashTable                底層是哈希表數據結構,線程是【同步】的  -->>  不能夠存入null鍵、null值
                            效率較低,故被【HashMap】替代
    ----|HashMap                採用哈希表實現  -->>  【無序】
                            底層是哈希表數據結構,線程是【不一樣步】的  -->>  能夠存入null鍵、null值
            【要保證鍵的惟一性,須要覆蓋hashCode()方法和equals()方法】
    ----|LinkedHashMap

    【經常使用方法:】
            添加:        V put(K key,V value)        能夠是相同的key值,可是添加的value值會覆蓋前面的
                    putAll(Map<? extends K , ? extends V> m)
                                            從指定映射中將全部映射關係複製到此映射中(可選操做)
            刪除:        remove(Object key)        刪除關聯對象,指定key對象
                    clear()                        清空集合對象
            獲取:        value get(Object key)        能夠用於判斷鍵是否存在的狀況。
            判斷:        boolean isEmpty()        若是此映射不包含鍵-值映射關係【即長度爲0】,則返回true,不然返回false
                    boolean containsKey(Object key)
                                            判斷集合中是否包含指定的key
                    boolean containsValue(Object value)
                                            判斷集合中是否包含指定的value
                                            當指定的鍵不存在的時候,返回的是null
            長度:        int size()                返回此映射中的鍵-值映射關係數

九、在何時該使用什麼樣的集合?

Collection        當咱們須要保存若干個對象的時候使用集合
      -->>  List        若是須要保留存儲順序、而且重複元素時,使用List
              -->>          若是查詢較多,使用ArrayList;
                      若是存取較多,使用LinkedList;
                      若是須要線程安全,使用Vector。
      -->>  Set        若是不須要保留存儲順序,而且要去掉重複元素時,使用Set
              -->>          若是須要將元素排序,使用TreeSet;
                      若是不須要排序,使用HashSet        【HashSet比TreeSet效率高】
                      若是須要保留存儲順序,同時要過濾重複元素,使用LinkedHashSet。

十、自定義對象時爲何要重寫toString()和equals()方法?

由於Object是自定義類的父類,Object類中的toString()方法返回的是哈希值;
    Object類中的equals()方法比較的是對象的地址值。

【去除集合中重複的元素】

代碼以下:
public class Demo{
    public static void main(String[] args){
        ArrayList arr = new ArrayList();
        Person p1 = new Person("jack",20);
        Person p2 = new Person("rose",18);
        Person p3 = new Person("rose",18);
        arr.add(p1);
        arr.add(p2);
        arr.add(p3);
        System.out.println(arr);
        ArrayList arr2 = new ArrayList();
        for(int i=0;i<arr.size();i++){
            Object obj = arr.get(i);
            Person p = (Person)obj;
            if(!arr2.contains(p)){
                arr2.add(p);
            }
        }
        System.out.println(arr2);
    }
}
class Person{
    private String name;
    private int age;
    public Person(){
    
    }
    public Person(String name,int age){
        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;
    }
    public int hashcode(){
        return this.name.hashCode() + age*37;
    }
    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;
    }
    public String toString(){
        return "name:" + this.name + "age:" + this.age;
    }
}

十一、Vector: 多線程安全、可是效率低 ---->> 描述的是一個線程安全的ArrayList。

特有的方法:
            void addElement(E obj)        在集合末尾添加元素
            E elementAt(int index)        返回指定角標的元素
            Enumeration element()        返回集合中的全部元素,封裝到Enumeration對象中
    Enumeration接口:
            boolean hasMoreElements()        測試此枚舉是否包含更多的元素
            E nextElement()                        若是此枚舉對象至少還有一個可提供的元素,則返回此枚舉的下一個元素
    【代碼以下:】
    public static void main(String[] args){
        Vector v = new Vector();
        v.addElement("aaa");
        v.addElement("bbb");
        v.addElement("ccc");
        // System.out.println(v.elementAt(2));
        Enumeration ens = v.elements();
        while(ens.hasMorreElements()){
            System.out.println(ens.nextElement());
        }
    }

十二、Iterable: 是Collection的父接口,實現Iterable的類能夠進行迭代,而且支持加強for循環

該接口只有一個方法,用於返回集合迭代器對象!                【獲取迭代器的方法iterator()】
            piblic interface Iterable<T>
    Iterator<T> iterator():該類主要用於遍歷集合對象,並描述了遍歷集合的常見方法
            boolean hasNext()        判斷集合中是否有元素,若是有元素能夠迭代,就返回true。
            E next()                返回迭代的下一個元素。
                                    若是沒有下一個元素,調用next()會拋出  -->>  NoSuchElementException
            void remove()                從迭代器指向的集合中移除迭代器返回的最後一個元素

【Iterator的for循環、清空】

public class Demo{
        ArrayList list = new ArrayList();
            // 增長:add() 將指定對象存儲到容器中
        list.add("計算機網絡");
        list.add("現代操做系統");
        list.add("java編程思想");
        list.add("java核心技術");
        list.add("java語言程序設計");
        System.out.println(list);
        for(Iterator it = list.iterator();it.hasNext();){
            // 迭代器的next()方法返回值類型是Object,全部要記得【類型強轉】
            String next = (String)it.next();
            System.out.println(next);
            it.remove();
        }
    }

【細節一:若是迭代器的指針已經指向了集合的末尾,那麼若是再調用next()會返回NoSuchElementException異常】
【細節二:若是調用remove()以前沒有調用next()方法是不合法的,會拋出IllegalStateException異常】
【細節三:當一個集合在循環中即便用引用變量操做集合,又使用迭代器操做集合對象,會拋出ConcurrentModificationException異常】

1三、爲何next()方法的返回值類型是Object呢?

爲了能夠接收任意類型的對象
    若是返回的時候不知道是什麼類型的,就定義爲object

1四、Iterator和ListIterator有什麼關係?

ListIterator是Iterator的子接口,是List集合特有的迭代器。
    Iterator在迭代時,只能對元素進行獲取【next()】和刪除【remove()】的操做;
    ListIterator在迭代list集合時,還能夠對元素進行添加【add(obj)】和修改【set(obj)】的操做。

1五、List集合特有的迭代器ListIterator

---->>  public interface ListIterator extends Iterator
ListIterator<E>   listIteraotr()
----| Iterator
            hasNext()
            next()
            remove()
    ----| ListIterator
                add(E e)                將指定的元素插入列表(可選操做)。
                                    該元素直接插入到next()返回的下一個元素的前面(若是有)
                void set(E o)        用指定的元素替換next()或previous()返回的 【最後】 一個元素
                hasPrevious()        逆向遍歷列表,列表迭代器有多個元素,則返回true
                previous()                返回列表中的前一個元素

1六、HashSet是如何判斷兩個元素重複的?

經過hashCode()方法和equals()方法來保證元素的惟一性,add()方法返回的是boolean類型
    【調用原理:HashSet集合在判斷元素是否相同,先判斷hashCode()方法,相同纔會判斷equals()方法;不相同不會調用equals()】

1七、HashSet和ArrayList集合在判斷元素時是否有相同的方法?

有:boolean contains(Object o)
    HashSet使用hashCode()和equals()方法,ArrayList使用eqauls()方法。

1八、給TreeSet指定排序規則:

方式一:【元素自身】具有比較性
              元素自身具有比較性,須要元素實現【Comparable接口】,重寫【compareTo方法】,
            也就是讓元素自身具有比較性,這種方式叫作元素的【天然排序】也叫作【默認排序】。
    方式二:【容器】具有比較性
             當元素自身不具有比較性,或者自身具有的比較性不是所須要的。
            那麼此時可讓容器自身具有。須要定義一個類實現【Comparator接口】,重寫【compare方法】,
            並將該接口的子類實例對象做爲參數傳遞給【TreeSet集合】的【構造方法】。
    注意:當Comparable比較方式和Comparator比較方式同時存在時,以【Comparator】的比較方式爲主;
    注意:在重寫compareTo或者compare方法時,必需要明確比較的主要條件相等時要比較次要條件。
            經過return 0 來判斷惟一性。

1九、爲何使用TreeSet存入字符串,字符串默認輸出是按升序排列的?

由於字符串實現了一個接口,叫作【Comparable接口】,字符串重寫了該接口的【compareTo()方法】,
    因此String對象具有了比較性。
    【自定義的元素(好比Person類、Book類)想要存入TreeSet集合,就必須實現Comparable接口,也就是要讓自定義對象具有比較性】
    【存入TreeSet集合的元素都要具有比較性:要實現Comparable接口、並重寫該接口的compareTo()方法】

20、總結:

看到array,就要想到角標。
    看到link, 就要想到first,last。
    看到hash, 就要想到hashCode,equals.
    看到tree, 就要想到兩個接口。Comparable,Comparator。

2一、TreeSet是如何保證元素的惟一性的?

經過【compareTo】或者【compare】方法來保證元素的惟一性。
    當Comparable接口中的compareTo()函數返回值爲【0】時,說明兩個對象相等,此時該對象不會被添加進來。

2二、使用TreeSet集合將字符串 String str = "8 10 15 5 2 7"; 的數值進行排序。

public class Demo{
        public static void main(String[] args){
            String str = "8 10 15 5 2 7";
            String strs = str.split(" ");
            TreeSet ts = new TreeSet();
            for(int x= 0;x<strs.length();x++){
                int y = Integer.parseInt(strs[x]);
                ts.add(y);
            }
            System.out.println(ts);
        }
    }

2三、遍歷Map集合的方式有哪些?

方式一:使用keySet
                    將Map轉成Set集合【keySet()】,經過Set的迭代器【Iterator】取出Set集合中的每個元素,
                    即Map集合中全部的鍵,再經過get()方法獲取鍵對應的值
                            Set<Integer> ks = map.keySet();
                            Iterator<Integer> it = ks.iterator();
                            while(it.hasNext()){
                                Integer key = it.next();
                                String value = map.get(key);
                            }
    方式二:經過values獲取全部值,可是不能獲取到key對象
                            Collection<String> vs = map.values();
                            Iterator<String> it = vs.iterator();
                            while(it.hasNext()){
                                String value = it.next();
                            }
    方式三:Map.Entry        -->>        public static interface Map.Entry<K,V>
                    經過Map中的entrySet()方法獲取存放Map.Entry<K,V>對象的Set集合        -->>        Set<Map.Entry<K,V>> entrySet()
                            Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
                            Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();
                            while(it.hasNext()){
                                Map.Entry<Integer,String> en = it.next();
                            }
                            Integer key = en.getKey();
                            String value = en.getValue();
相關文章
相關標籤/搜索