java常用的集合,這幾個你都會麼?

2021-02-13 Java研究所


大家好,這裡是java研究所。

java中的集合比較多,今天我們來熟悉一下常用的幾個,了解其特點,用起來會更順手一些,下面先看下類圖

1、List接口

可以存放重複的元素,2個常用的實現類

1.1、ArrayList放入順序和迭代的順序是一樣的,也就是說元素是有序的數組的特點是,通過索引訪問的時候,時間複雜度是O(1)但是向某個位置插入數據,由於涉及元素的後移,所以時間複雜度是O(n)但是在末尾追加元素,沒有數據的移動操作,時間複雜度是O(1)刪除某個元素,需要先找到個元素,然後還需要將後面的元素前移,時間複雜度是O(n)刪除某個位置的元素,需要將後面的元素前移,時間複雜度是O(n)
@org.junit.Test
public void arrayList() {
    ArrayList<Integer> arrayList = new ArrayList<>();
    for (Integer i = 10; i < 20; i++) {
        arrayList.add(i);
    }
    //放入的順序和迭代的順序一樣
    arrayList.forEach(System.out::println);
}

輸出

10
11
12
13
14
15
16
17
18
19

1.2、LinkedList由於採用鍊表存放數據,所以查找某個位置的數據,涉及到鍊表的遍歷,所以時間複雜度是O(n)在某個位置插入元素,也需要先定位到那個位置,定位位置,只能通過遍歷的方式,所以時間複雜度是O(n)刪除某個元素,需要先找到個元素,然後改變一下鍊表的指針就可以了,時間複雜度是O(n)刪除某個位置的元素,需要先找到這個位置,然後改變一下鍊表的指針就可以了,時間複雜度是O(n)
@org.junit.Test
public void linkedList() {
    LinkedList<Integer> linkedList = new LinkedList<>();
    for (Integer i = 10; i < 20; i++) {
        linkedList.add(i);
    }
    //放入的順序和迭代的順序一樣
    linkedList.forEach(System.out::println);
}

1.3、小結若應用程式對數據有較多的隨機訪問,ArrayList對象要優於LinkedList對象若應用程式有更多的插入或者刪除操作,較少的數據讀取,LinkedList對象要優於ArrayList對象不過ArrayList的插入,刪除操作也不一定比LinkedList慢,若在List靠近末尾的地方插入,那麼ArrayList只需要移動較少的數據,而LinkedList則需要一直查找到列表尾部,反而耗費較多時間,這時ArrayList就比LinkedList要快2、Set接口

存入的元素會自動去重,3個常用的實現類

2.1、HashSet放入的元素是無序的,比如放入的是a、b、c,但是迭代出來的順序可能就亂掉了

下面放入a/b/c/1/2/3,然後迭代輸出順序亂了,和放入的順序不一樣了

@org.junit.Test
public void hashSet() {
    HashSet<String> hashSet = new HashSet<>();
    hashSet.add("a");
    hashSet.add("b");
    hashSet.add("c");
    hashSet.add("1");
    hashSet.add("2");
    hashSet.add("3");
    hashSet.forEach(System.out::println);
}

輸出

a
1
b
2
c
3

2.2、LinkedHashSet元素是有序的,即放進去的順序和迭代出來的順序是一致的

看下面案例,放入順序和迭代輸出的順序一致

@org.junit.Test
public void linkedHashSet() {
    LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
    linkedHashSet.add("a");
    linkedHashSet.add("b");
    linkedHashSet.add("c");
    linkedHashSet.add("1");
    linkedHashSet.add("2");
    linkedHashSet.add("3");
    linkedHashSet.forEach(System.out::println);
}

輸出

a
b
c
1
2
3

2.3、TreeSet

會對放入的元素進行排序,排序規則如下:

創建TreeMap的時候,可以指定排序器,若不指定排序,那麼放入的元素必須實現java.lang.Comparable接口,否則add元素會報異常,若通過構造器指定了排序器,並且元素也實現了java.lang.Comparable接口,那麼會按照構造函數指定的排序器進行排序。

案例1:自然順序

下面放入Integer類型的元素,Integer類型默認實現了java.lang.Comparable接口,會按照升序排序。

@org.junit.Test
public void treeSetTest1() {
    TreeSet<Integer> treeSet = new TreeSet<>();
    treeSet.add(10);
    treeSet.add(5);
    treeSet.add(4);
    treeSet.add(20);
    treeSet.forEach(System.out::println);
}

結果按升序輸出

4
5
10
20

案例2:放入自定義的元素

SchoolReport:表示成績單信息,實現了Comparable接口,這個接口有個compareTo方法,這個方法中我們按照score升序排序

public static class SchoolReport implements Comparable<SchoolReport> {
    //分數
    private int score;
    //姓名
    private String name;

    public SchoolReport(int score, String name) {
        this.score = score;
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Score{" +
                "score=" + score +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public int compareTo(SchoolReport o) {
        return Integer.compare(this.score, o.score);
    }
}

測試代碼如下,然後迭代輸出

@org.junit.Test
public void treeSetTest2() {
    TreeSet<SchoolReport> treeSet = new TreeSet<>();
    treeSet.add(new SchoolReport(10, "張三"));
    treeSet.add(new SchoolReport(5, "李四"));
    treeSet.add(new SchoolReport(15, "王五"));
    treeSet.forEach(System.out::println);
}

結果如下,按照score升序排序了

Score{score=5, name='李四'}
Score{score=10, name='張三'}
Score{score=15, name='王五'}

案例3:通過構造器指定比較器

先看一下構造器如下,需要傳入java.util.Comparator類型的比較器,用來對放入的元素進行排序

public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

下面案例,比較器為按照score的降序排序

@org.junit.Test
public void treeSetTest3() {
    Comparator<SchoolReport> scoreDescComparator = Comparator.comparingInt(SchoolReport::getScore).reversed();
    TreeSet<SchoolReport> treeSet = new TreeSet<>(scoreDescComparator);
    treeSet.add(new SchoolReport(10, "張三"));
    treeSet.add(new SchoolReport(5, "李四"));
    treeSet.add(new SchoolReport(15, "王五"));
    treeSet.forEach(System.out::println);
}

下面看結果,按照score的降序輸出了

Score{score=15, name='王五'}
Score{score=10, name='張三'}
Score{score=5, name='李四'}

2.4、小結HashSet內部使用HashMap實現的,所以添加、修改、刪除,都是上面3個集合中最快的,如果你元素的順序和排序沒有要求,那麼要用set的時候,這個就是首選若要求放入的順序和迭代出來的順序一致,那麼使用LinkedHashSet若需要對放入的元素進行排序,那麼使用TreeSet3、Map接口

key->value的方式存放數據,key不能重複。

常用的3個實現

3.1、HashMap放入的元素是無序的,比如放入的key是a、b、c,但是迭代出來的順序可能就亂掉了

下面代碼放入了3個元素,key分別是10/5/15,然後迭代輸出,順序亂掉了

@org.junit.Test
public void hashMap() {
    HashMap<Integer, String> hashMap = new HashMap<>();
    hashMap.put(10, "張三");
    hashMap.put(5, "李四");
    hashMap.put(15, "王五");
    hashMap.forEach((k, v) -> {
        System.out.println(k + ":" + v);
    });
}

結果

5:李四
10:張三
15:王五

3.2、LinkedHashMap元素是有序的,即放進去的順序和迭代出來的順序是一致的

看下面案例,放入順序和迭代輸出的順序一致

@org.junit.Test
public void linkedHashMap() {
    LinkedHashMap<Integer, String> linkedHashMap = new LinkedHashMap<>();
    linkedHashMap.put(10, "張三");
    linkedHashMap.put(5, "李四");
    linkedHashMap.put(15, "王五");
    linkedHashMap.forEach((k, v) -> {
        System.out.println(k + ":" + v);
    });
}

輸出

10:張三
5:李四
15:王五

3.3、TreeMap

會對放入的元素按照key進行排序,排序規則如下:

創建TreeMap的時候,可以指定排序器,若不指定排序,那麼key必須實現java.lang.Comparable接口,否則add元素會報異常,若通過構造器指定了排序器,並且key也實現了java.lang.Comparable接口,那麼會按照構造函數指定的排序器進行排序。

案例1:自然順序

下面key為Integer類型的元素,Integer類型默認實現了java.lang.Comparable接口,會按照升序排序。

@org.junit.Test
public void treeMap1() {
    TreeMap<Integer, String> treeMap = new TreeMap<>();
    treeMap.put(10, "張三");
    treeMap.put(5, "李四");
    treeMap.put(15, "王五");
    treeMap.forEach((k, v) -> {
        System.out.println(k + ":" + v);
    });
}

結果按升序輸出

5:李四
10:張三
15:王五

案例2:放入自定義的元素

SchoolReport:表示成績單信息,實現了Comparable接口,這個接口有個compareTo方法,這個方法中我們按照score升序排序

public static class SchoolReport implements Comparable<SchoolReport> {
    //分數
    private int score;
    //姓名
    private String name;

    public SchoolReport(int score, String name) {
        this.score = score;
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Score{" +
                "score=" + score +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public int compareTo(SchoolReport o) {
        return Integer.compare(this.score, o.score);
    }
}

測試代碼如下,然後迭代輸出

@org.junit.Test
public void treeMap2() {
    TreeMap<SchoolReport, String> treeMap = new TreeMap<>();
    treeMap.put(new SchoolReport(10, "張三"), "哈哈哈");
    treeMap.put(new SchoolReport(5, "李四"), "哈哈哈");
    treeMap.put(new SchoolReport(15, "王五"), "哈哈哈");
    treeMap.forEach((k, v) -> {
        System.out.println(k + ":" + v);
    });
}

結果如下,按照score升序排序了

Score{score=5, name='李四'}:哈哈哈
Score{score=10, name='張三'}:哈哈哈
Score{score=15, name='王五'}:哈哈哈

案例3:通過構造器指定比較器

先看一下構造器如下,需要傳入java.util.Comparator類型的比較器,用來對放入的元素進行排序

public TreeMap(Comparator<? super K> comparator) {
    this.comparator = comparator;
}

下面案例,比較器為按照score的降序排序

@org.junit.Test
public void treeMap3() {
    Comparator<SchoolReport> scoreDescComparator = Comparator.comparingInt(SchoolReport::getScore).reversed();
    TreeMap<SchoolReport, String> treeMap = new TreeMap<>(scoreDescComparator);
    treeMap.put(new SchoolReport(10, "張三"), "哈哈哈");
    treeMap.put(new SchoolReport(5, "李四"), "哈哈哈");
    treeMap.put(new SchoolReport(15, "王五"), "哈哈哈");
    treeMap.forEach((k, v) -> {
        System.out.println(k + ":" + v);
    });
}

下面看結果,按照score的降序輸出了

Score{score=15, name='王五'}:哈哈哈
Score{score=10, name='張三'}:哈哈哈
Score{score=5, name='李四'}:哈哈哈

3.4、小結HashMap添加、修改、刪除,都是上面3個集合中最快的,如果你元素的順序和排序沒有要求,那麼要用Map的時候,HashMap就是首選若要求放入的順序和迭代出來的順序一致,那麼使用LinkedHashMap若需要對放入的元素進行排序,那麼使用TreeMap4、送書福利

這邊整理了幾百本計算機相關的電子書,下面是部分截圖,常見的基本上都有,獲取方式,掃描下面二維碼,發送:電子書

相關焦點

  • java基礎教程:Collection集合,Collection 常用API
    集合概述在前面基礎班我們已經學習過並使用過集合ArrayList<E> ,那麼集合到底是什麼呢?集合:集合是java中提供的一種容器,可以用來存儲多個數據。集合和數組既然都是容器,它們有什麼區別呢?數組的長度是固定的。集合的長度是可變的。
  • 程式設計師:java集合介紹,帶你深入理解list集合
    List介紹在Collection中,List集合是有序的,可對其中每個元素的插入位置進行精確地控制,可以通過索引來訪問元素,遍曆元素。在List集合中,我們常用到ArrayList和LinkedList這兩個類。ArrayList集合1,ArrayList底層通過數組實現,隨著元素的增加而動態擴容。
  • Java 集合框架面試問題集錦
    很好地理解集合框架,可以幫助你理解和利用Java的一些高級特性。下面是面試Java核心技術的一些很實用的問題。Q:最常見的數據結構有哪些,在哪些場景下應用它們?A. 大部分人都會遺漏樹和圖這兩種數據結構。樹和圖都是很有用的數據結構。如果你在回答中提及到它們的話,面試者可能會對你進行進一步進行的考核。Q:你如何自己實現List,Set和Map?
  • 死磕 java所有集合之終結篇
    (19)比較古老的集合Vector和Stack有什麼缺陷?關於List的問題大概就這麼多,你都能回答上來嗎?(44)為什麼Redis選擇使用跳表而不是紅黑樹來實現有序集合?關於Map的問題大概就這麼多,你都能回答上來嗎?
  • java集合詳解合集
    一旦在數組初始化時指定了這個數組長度,這個數組長度就是不可變的,如果我們需要保存一個可以動態增長的數據(在編譯時無法確定具體的數量),java的集合類就是一個很好的設計方案了。集合類主要負責保存、盛裝其他數據,因此集合類也被稱為容器類。
  • 50道Java集合經典面試題(收藏版)
    Collection表示一個集合,包含了一組對象元素。如何維護它的元素對象是由具體實現來決定的。因為集合的具體形式多種多樣,例如list允許重複,set則不允許。而克隆(clone)和序列化(serializable)只對於具體的實體,對象有意義,你不能說去把一個接口,抽象類克隆,序列化甚至反序列化。
  • java 基礎 之 集合 Map
    這是一個類似於 SortedSetDemo.java 的示例,顯示了 TreeMap 的這種額外行為:// collectiontopics/SortedMapDemo.java// What you can do with a TreeMapimport java.util.
  • 考考基礎部分,談談Java集合中HashSet的原理及常用方法
    HashSet概述 HashSet是Java集合Set的一個實現類,Set是一個接口,其實現類除HashSet之外,還有TreeSet,並繼承了Collection,HashSet集合很常用,同時也是程式設計師面試時經常會被問到的知識點,下面是結構圖
  • JAVA多線程 集合同步
    特別注意:不要通過迭代器iterator自己的方法(比如add(), set(), remove())去修改集合CopyOnWriteArrayList中的元素,這會引起拋出UnsupportedOperationException異常。2.
  • java 集合類之List(二)
    引言昨天介紹了java集合類框架,接下來會詳細聊一下各個集合類的適用場景和需要注意的地方。今天主要介紹一下List,如有錯誤之處,還望指正。ListList 是java集合中最簡單,也是最常用的一種集合。List存儲的是一種有序、不重複的數據。比如產品列表、商品列表等等。
  • java常用幾大類庫
    你要找誰?在輸入框裡輸入,然後回車。 看包。java.lang下的類不需要導包,其他需要。 看類的解釋和說明。 學習構造方法。 使用成員方法。第2章 Scanner類了解了API的使用方式,我們通過Scanner類,熟悉一下查詢API,並使用類的步驟。2.1 什麼是Scanner類一個可以解析基本類型和字符串的簡單文本掃描器。
  • java集合總結-複習
    Map第一張圖裡 List有序有重複,Set無序無重複,這些基本都書序java程式設計師必須知道的一件事情.對我個人來有以下幾個不明白的點:自己給自己提問 然後自己回答,嘿嘿。ArrayList 底層為數組為什麼查詢快增刪慢?
  • 40個Java集合面試問題和答案
    Java1.5引入了泛型,所有的集合接口和實現都大量地使用它。泛型允許我們為集合提供一個可以容納的對象類型,因此,如果你添加其它類型的任何元素,它會在編譯時報錯。這避免了在運行時出現ClassCastException,因為你將會在編譯時得到報錯信息。泛型也使得代碼整潔,我們不需要使用顯式轉換和instanceOf操作符。
  • Java 枚舉類型使用,枚舉集合介紹
    枚舉類型從前面的數據類型章節可知 Java 中並沒有枚舉類型,但通過 Java API 中的 java.lang.Enum 枚舉類我們可以定義枚舉類型數據,本質上還是一個類類型。字符竄類型也是一樣,通過 String 類生成,每一個雙引號中的字符串編譯後都會創建對應的字符串 String 對象。為什麼要定義枚舉類型?
  • Java 集合框架看這一篇就夠了
    那麼這兩大接口的不同之處在於:就是單身狗放 Collection 裡面,couple 就放 Map 裡。(所以你屬於哪裡?還有另外一個方法 addAll(),可以把另一個集合裡的元素加到此集合中。boolean addAll(Collection<?
  • 黑馬程式設計師Java教程:Java基礎教程之MAP集合
    1.1 概述現實生活中,我們常會看到這樣的一種集合:IP位址與主機名,身份證號與個人,系統用戶名與系統用戶對象等,這種一一對應的關係,就叫做映射。Java提供了專門的集合類用來存放這種對象關係的對象,即java.util.Map接口。
  • JAVA校招題基礎知識點複習第六天(一張圖搞懂所有集合特點)
    集合其實和數組一樣都是java中提供的一種容器,可以用來存儲多個數據。既然集合和數組都容器,那麼他們有什麼區別呢?1、數組的長度是固定的,集合的長度是可變的。3、集合存儲的都是對象。而且對象的類型可以不一致。在開發中一般當對象多的時候,使用集合進行存儲。了解完集合與數組的區別,讓我們來看看在JAVA中都為我們提供了哪些集合?
  • 給Java新手的一些建議——Java知識點歸納(Java基礎部分)
    Java的運行(基礎必備)這條可能出看很簡單,java程序的運行誰不會呢?不過很多時候, 我們只是單純通過IDE去執行java程序,底層IDE又是如何執行java程序呢?很多人並不了解。這個知識點是最最基本的java開發者需要掌握的,初學java,第一個肯定是教你如何在命令行中執行java程序,但是很多人一旦把java學完了,IDE用上了,就把這個都忘了。
  • 這裡有675道Java面試題,你準備好接招了嗎?(完整版)
    java可以歸類到那種?102.簡述操作符(&,|)與操作符(&&,||)的區別&和&&的聯繫(共同點)103.try{}裡面有一個return語句,那麼緊跟在這個try後的finally, 裡面的語句在異常出現後,都會執行麼?為什麼?
  • 你必須掌握的 21 個 Java 核心技術!
    這個知識點是最最基本的java開發者需要掌握的,第一個肯定是教你如何在命令行中執行java程序,但是很多人一旦把java學完了,IDE用上了,就把這個都忘了。對象和實例在這方面,開發者需要了解class和instance的概念以及之間的差別, 這是java面向對象特性的一個基礎。