Java基礎之集合 List、Map和Set

List介紹

List是Java中比較常用的集合類型之一,它是一個接口,繼承于Collection接口,其中實現(xiàn)類中常見的有ArrayList、LinkedList、Vector等子類。
List中元素可以重復,并且是有序的。(這里的有序指的是按照放入的順序進行存儲。)
1、ArrayList底層是數(shù)組實現(xiàn)的,是一種可以動態(tài)增長和縮減的索引序列。數(shù)組和數(shù)組列表中有一個重大的缺陷:從數(shù)組的中間位置刪除一個元素要付出很大的代價,因為在數(shù)組中處于被刪除元素之后的所有元素都要向數(shù)組前端移動,在數(shù)組中間插入元素也是如此,所以數(shù)組在刪除和插入的操作上效率低。
實現(xiàn):

public void invoke(){
        //初始化
        List<String> list=new ArrayList<>();
        //賦值
        list.add("one");
        list.add("two");
        list.add("one");
        list.add("one");
        list.add("abc");
        Log.d("TestList","size===="+list.size());
         //遍歷集合
        for (int i = 0; i < list.size(); i++) {
            String str=list.get(i);
            Log.d("TestList",str);
        }

        Log.d("TestList","------------remove------------");
        //for循環(huán)刪除元素
        for (int i = 0; i < list.size(); i++) {
            String str=list.get(i);
            if(str.equals("one")){
                list.remove(i);
            }
            Log.d("TestList",str);
        }

    }
TestList: size====5
TestList: [one, two, one, one, abc]
TestList: ----for循環(huán)remove----
TestList: [two, one, abc]

通過ArrayList的remove方法進行刪除元素打印出的結果中還存在one,出現(xiàn)刪除的元素并沒有完全被刪除的情況。

        Log.d("TestList","----遍歷器刪除----");
        for (String s : list) {
            if(s.equals("one")){
                list.remove(s);
            }
        }
        Log.d("TestList",list.toString());
   通過遍歷器刪除,報以下異常
   Caused by: java.util.ConcurrentModificationException
        Log.d("TestList","----Iterator----");
        //迭代器刪除元素
        Iterator iterator=list.iterator();
        while (iterator.hasNext()) {
            if(iterator.next().equals("one")){
                iterator.remove();
            }
        }
        Log.d("TestList",list.toString());
TestList: ----Iterator----
TestList: [two, abc]

通過迭代器判斷進行刪除元素,打印結果正常。
綜上所述,在對ArrayList進行遍歷刪除時,建議使用迭代器Iterator進行遍歷刪除。(面試中被問到的幾率還是不小的)
2、LinkdeList底層是鏈表實現(xiàn)的。是一種可以在任何位置進行高效的插入和刪除的有序序列。鏈表將每個對象存放在獨立的結點中,每個結點還存放著序列中下一個結點的引用。所以在鏈表中刪除一個元素是一個很輕松的操作,只需要對被刪除元素附近的結點更新一下即可。在Java程序語言中,所有鏈表實際上都是雙向鏈接的(doubly linked),每個結點還存放著指向前驅結點的引用。
實現(xiàn):

 public void invoke(){
        List<String> list=new LinkedList<>();
        list.add("aaa");
        list.add("abc");
        list.add("aa");
        Log.d("Testlinked",list.toString()+",size===="+list.size());
    }
Testlinked: [aaa, abc, aa],size====5
雙向鏈表
        Log.d("Testlinked","-----Iterator-----");
        Iterator<String> iterator=list.iterator();
        String first=iterator.next();
        String second=iterator.next();
        iterator.remove();
        Log.d("Testlinked",list.toString());
Testlinked: -----Iterator-----
Testlinked: [aaa, aa]
從鏈表中刪除一個元素

3、Vector和ArrayList一樣底層都是數(shù)據(jù)實現(xiàn)的,Vector是線程安全的,ArrayList、LinkedList都是線程不安全的,即在多線程下修改數(shù)據(jù)可能會造成數(shù)據(jù)錯亂,重復增刪等問題。Vector中的很多重要方法都是用synchronized實現(xiàn)同步,保證線程安全。在多線程下如果要保證線程安全,那么使用Vector比較好,但是在保證線程安全的同時效率也會下降。如果你的程序不涉及到線程安全問題,那么使用ArrayList是更好的選擇(因為Vector使用synchronized,必然會影響效率)。
Vector和ArrayList二者之間還有一個區(qū)別,就是擴容策略不一樣。在List被第一次創(chuàng)建的時候,會有一個初始大小,隨著不斷向List中增加元素,當List認為容量不夠的時候就會進行擴容。Vector缺省情況下自動增長原來一倍的數(shù)組長度,ArrayList增長原來的50%。

綜上所述,在需要頻繁讀取集合中的元素時,使用ArrayList效率較高,而在插入和刪除操作較多時,使用LinkedList效率較高。使用Vector可以多線程下保證修改數(shù)據(jù)線程安全(當然,你也可以使用ArrayList并自己實現(xiàn)同步)。

Set介紹

Set也是ava中比較常用的集合類型之一,它是一個接口,和List一樣繼承于Collection接口,其中實現(xiàn)類中常見的有HashSet、TreeSet等子類。Set是沒有重復元素的集合,是無序的。
1、HashSet實現(xiàn)了基于散列表的集??梢杂胊dd方法添加元素??梢钥焖俚牟榭茨硞€元素是否出現(xiàn)在集中,只在某個桶中查找元素,而不必查看集合中的所有元素。HashSet不能存儲重復的值,如果key已存在內容會被覆蓋。允許null值,非線程安全。
實現(xiàn):

public void invoke(){
        Set<String> set=new HashSet<>();
        set.add("abc");
        set.add("ab");
        set.add("ccc");
        Log.d("TestSet",set.toString());
        //存儲null值
        set.add(null);
        Log.d("TestSet",set.toString());
        set.add("oi");
        Log.d("TestSet",set.toString());
        //存儲相同的值
        set.add("oi");
        Log.d("TestSet",set.toString());
        //遍歷
        Iterator<String> iterator=set.iterator();
        while (iterator.hasNext()) {
        String str=iterator.next();
            Log.d("TestSet",str+"");
        }
    }
TestSet: [abc, ab, ccc]
TestSet: [null, abc, ab, ccc]
TestSet: [null, abc, oi, ab, ccc]
TestSet: [null, abc, oi, ab, ccc]

2、TreeSet類與散列集十分相似,不過,它比散列集有所改進。樹集是一個有序的集合??梢砸匀我忭樞驅⒃夭迦氲郊现?。在對集合進行遍歷時,每個值會自動的按照排序后的順序呈現(xiàn)。
實現(xiàn):

 public void invoke(){
        Set<Integer> set=new TreeSet<>();
        set.add(777);
        set.add(1);
        set.add(23);
        set.add(98);
        set.add(33);
        set.add(66);
        Log.d("TestTree",set.toString());
    }
TestTree: [1, 23, 33, 66, 98, 777]

Map介紹

Map是以鍵值對形式存儲數(shù)據(jù),不能存儲重復的元素。有HashMap、LinkedHashMap、TreeMap等子類。
1、HashMap是哈希表結構,不保證存取順序,允許null鍵或者null值,效率較高。實現(xiàn)了Map接口。

public void invoke(){
        Map map=new HashMap();
        map.put("aaa","aaa");
        Log.d("TestMap",map.toString());
        map.put(null,null);
        Log.d("TestMap",map.toString());

        Log.d("TestMap","aaa==="+map.get("aaa"));
        Log.d("TestMap","null==="+map.get(null));
}
TestMap: {aaa=aaa}
TestMap: {null=null, aaa=aaa}
TestMap: aaa===aaa
TestMap: null===null
public void invoke(){
        Map map=new HashMap();
        map.put("aaa","aaa");
        map.put("a","aaa");
        map.put("aa","aaa");
        Log.d("TestMap",map.toString());
        //遍歷Map
        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            Log.d("TestMap", "Key = " + key + ", Value = " + value);
        }
}
TestMap: {aa=aaa, a=aaa, aaa=aaa}
TestMap: Key = aa, Value = aaa
TestMap: Key = a, Value = aaa
TestMap: Key = aaa, Value = aaa

2、LinkedHashMap帶雙向鏈表的哈希表結構,保持存取順序,允許null鍵和null值,非線程安全,效率較高。

public void invoke(){
        Map maplink=new LinkedHashMap();
        maplink.put("aaa","123456789");
        maplink.put("aaa","123456789");
        maplink.put("aaa","123456789");
        maplink.put("aaa","123456789");
        Log.d("TestMap",maplink.toString());
}
TestMap: {aaa=123456789}

3、TreeMap平衡排序二叉樹(紅黑樹)結構,按自然排序或比較器存入元素以保證元素順序。非線程安全。

這篇文章主要鞏固一下幾種集合類相關的基礎知識,也加深一下印象,如果文章中有錯誤有問題,歡迎指出,以后會日益完善。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容