天天看點

Java集合-Collection一、集合架構的概述二、集合架構

文章目錄

  • 一、集合架構的概述
    • 數組與集合
      • 1.集合、數組都是對多個資料進行存儲操作的結構,簡稱 Java容器。
      • 1.1 數組在存儲多個資料方面的特點:
      • 1.2 數組在存儲多個資料方面的缺點:
      • 集合存儲的優點
  • 二、集合架構
    • Collection接口方法
    • Iterator 疊代器接口
      • Iterator 接口的方法
        • hasNext() , next()
        • remove() 方法與foreach 循環周遊集合元素
        • 代碼實作
    • Collection 子接口之一:List 接口
      • List接口概述:元素有序、且可重複
      • List接口中的常用方法
        • 總結:常用方法
      • List實作類之一: ArrayList
        • ArrayList的分析:
        • 代碼實作
      • List實作類之二: LinkedList
        • LinkedList的分析:
      • List實作類之三: Vector
      • 面試題:ArrayList、LinkedList、Vector三者的異同?談談你的了解? ArrayList 底層是什麼?擴容機制? Vector 和 ArrayList 的最大差別
    • Collection 子接口之二:Set 接口
      • Set接口概述:存儲無序的、不可重複的資料
      • Set實作類之一: HashSet
        • 代碼實作
      • Set實作類之二: LinkedHashSet
      • Set實作類之三:TreeSet
    • 周遊Collection的兩種方式
Arrays.asList (…) 方法傳回的 List 集合 既 不是 ArrayList 執行個體,也不是Vector 執行個體。 Arrays.asList (…) 傳回值是一個固定長度的 List 集合

一、集合架構的概述

數組與集合

1.集合、數組都是對多個資料進行存儲操作的結構,簡稱 Java容器。

說明:此時的存儲,主要指的是記憶體層面的存儲,不涉及到持久化的存儲(.txt,.jpg,.avi,資料庫中)

1.1 數組在存儲多個資料方面的特點:

  • 一旦初始化以後,其長度就确定了。
  • 數組一旦定義好,其元素的類型也就确定了。我們也就隻能操作指定類型的資料了。

    比如:String[ ] arr ; int[ ] arr1 ; Object[ ] arr2;

1.2 數組在存儲多個資料方面的缺點:

  • 一旦初始化以後,其長度就不可修改。
  • 數組中提供的方法非常有限,對于添加、删除、插入資料等操作,非常不便,同時效率不高。
  • 擷取數組中實際元素的個數的需求,數組沒有現成的屬性或方法可用
  • 數組存儲資料的特點:有序、可重複。對于無序、不可重複的需求,不能滿足。

集合存儲的優點

解決數組存儲資料方面的弊端。

可以用于存儲數量不等的多個 對象 ,還可用于儲存具有映射關系的關聯數組

二、集合架構

Java集合可分為Collection和Map兩種體系

  • Collection接口:單列集合,用來存儲一個一個的對象
    • List接口:存儲有序的、可重複的資料。 -->“動态”數組
      • ArrayList、LinkedList、Vector
    • Set接口:存儲無序的、不可重複的資料 -->高中講的“集合”
      • HashSet、LinkedHashSet、TreeSet

Collection 接口繼承樹

Java集合-Collection一、集合架構的概述二、集合架構
  • Map接口:雙列集合,用來存儲一對(key - value)一對的資料 -->高中函數:y = f(x)
    • HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
    Map 接口繼承樹
    Java集合-Collection一、集合架構的概述二、集合架構

Collection接口方法

Collection coll = new ArrayList();

  1. 添加 add(Object obj) addAll(Collection coll)
//add(Object e):将元素e添加到集合coll中
        coll.add("AA");
        coll.add("BB");
        coll.add(123);//自動裝箱
        coll.add(new Date());
        //addAll(Collection coll1):将coll1集合中的元素添加到目前的集合中
        Collection coll1 = new ArrayList();
        coll1.add(456);//自動裝箱
        coll1.add("CC");
        coll.addAll(coll1);
           
  1. 擷取有效元素的個數 int size()
//size():擷取添加的元素的個數
		System.out.println(coll.size());//6
           
  1. 清空集合 void clear()

    coll.clear();

  2. 是否是空集合 boolean isEmpty()

    System.out.println(coll.isEmpty());

  3. 是否包含某個元素 contains containsAll

    boolean contains(Object obj):是通過元素的equals方法來判斷是否是同一個對象

    boolean containsAll(Collection c):也是調用元素的equals方法來比較的。拿兩個集合的元素挨個比較。

@Test
    public void test1(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry",20));//匿名對象
        coll.add(new String("Tom"));
        coll.add(false);
        //1.contains(Object obj):判斷目前集合中是否包含obj
        //我們在判斷時會調用obj對象所在類的equals()。
        boolean contains = coll.contains(123);
        System.out.println(contains);
        System.out.println(coll.contains(new String("Tom")));
        System.out.println(coll.contains(new Person("Jerry",20)));//true
        //2.containsAll(Collection coll1):判斷形參coll1中的所有元素是否都存在于目前集合中。
        Collection coll1 = Arrays.asList(123,4567);
        System.out.println(coll.containsAll(coll1));
    }
           
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {this.name = name;this.age = age;}
    public Person() { }
    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 boolean equals(Object o) {
        System.out.println("這是重寫的equals");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}
           
  1. 删除 remove removeAll

    boolean remove(Object obj) :通過元素的equals方法判斷是否是要删除的那個元素。隻會删除找到的第一個元素

    collection.remove(1234);

    boolean removeAll(Collection coll):取目前集合的差集

    差集:從目前集合中移除collection1中所有的元素。

    collection.removeAll(collection1);

  2. 取兩個集合的交集 retainAll

    boolean retainAll(Collection c): 擷取目前集合和collection1集合的交集,并傳回給目前集合

  3. 集合是否相等 boolean equals(Object obj)
public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry",20));
        coll.add(new String("Tom"));
        coll.add(false);

        //7.retainAll(Collection coll1):交集:擷取目前集合和coll1集合的交集,并傳回給目前集合
        Collection coll1 = Arrays.asList(123,456,789);
        coll.retainAll(coll1);
        System.out.println(coll);

        //8.equals(Object obj):要想傳回true,需要目前集合和形參集合的元素都相同。
        Collection coll1 = new ArrayList();
        coll1.add(456);
        coll1.add(123);
        coll1.add(new Person("Jerry",20));
        coll1.add(new String("Tom"));
        coll1.add(false);

        System.out.println(coll.equals(coll1));//false


    }
           
  1. 轉成對象數組 Object[] toArray()
  2. 擷取集合對象的哈希值 hashCode()
  3. 周遊 iterator():傳回疊代器對象,用于集合周遊
public void test4(){
        Collection coll = new ArrayList();
        coll.add(123);
        coll.add(456);
        coll.add(new Person("Jerry",20));
        coll.add(new String("Tom"));
        coll.add(false);

        //10.hashCode():傳回目前對象的哈希值
        System.out.println(coll.hashCode());

        //9.集合 --->數組:toArray()
        Object[] arr = coll.toArray();
        for(int i = 0;i < arr.length;i++){
            System.out.println(arr[i]);
        }

        //拓展:數組 --->集合:調用Arrays類的靜态方法asList()
        List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});
        System.out.println(list);

        List arr1 = Arrays.asList(new int[]{123, 456});
        System.out.println(arr1.size());//1

        List arr2 = Arrays.asList(new Integer[]{123, 456});
        System.out.println(arr2.size());//2

        //9.iterator():傳回Iterator接口的執行個體,用于周遊集合元素。放在IteratorTest.java中測試
    }
           
③ 普通的循環
           

Iterator 疊代器接口

概述

集合元素的周遊操作,使用疊代器Iterator接口

  • Iterator 對象稱為疊代器 (設計模式的一種 ),主要用于周遊 Collection集合中的元素。
  • GOF 給疊代器模式的定義為:提供一種方法通路一個容器 ( 對象中各個元素,而又不需暴露該對象的内部細節。 疊代器模式,就是為容器而生。 類似于“公共汽車上的售票員”、“火車上的乘務員”、 “空姐 。
  • Collection 接口繼承了 java.lang.Iterable 接口,該接口有一個 iterator() 方法,那麼所有實作了 Collection 接口的集合類都有一個 iterator() 方法,用以傳回一個實作了Iterator 接口的對象 。
  • Iterator 僅用于周遊集合 ,Iterator 本身并不提供承裝對象的能力。如果需要建立Iterator 對象,則必須有一個被疊代的集合。

Iterator 接口的方法

  1. 常用的内部的方法:hasNext() , next()和remove()
  2. 集合對象每次調用iterator()方法都得到一個全新的疊代器對象,預設遊标都在集合的第一個元素之前。
  3. 内部定義了remove(),可以在周遊的時候,删除集合中的元素。此方法不同于集合直接調用remove()

hasNext() , next()

Java集合-Collection一、集合架構的概述二、集合架構
Java集合-Collection一、集合架構的概述二、集合架構
public void test1(){
        Collection coll = new ArrayList();
        coll.add(123);coll.add(456);
        coll.add(new Person("Jerry",20));
        coll.add(new String("Tom"));
        coll.add(false);

        Iterator iterator = coll.iterator();
        //方式一:
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        System.out.println(iterator.next());
//        //報異常:NoSuchElementException
//        System.out.println(iterator.next());

        //方式二:不推薦
//        for(int i = 0;i < coll.size();i++)
//			{System.out.println(iterator.next());}

        //方式三:推薦
        hasNext():判斷是否還有下一個元素
        while(iterator.hasNext()){
            //next():①指針下移 ②将下移以後集合位置上的元素傳回
            System.out.println(iterator.next());
        }

		//錯誤方式一:
//        Iterator iterator = coll.iterator();
//        while((iterator.next()) != null){
//            System.out.println(iterator.next());
//        }
        //錯誤方式二:
//集合對象每次調用iterator()方法都得到一個全新的疊代器對象,預設遊标都在集合的第一個元素之前。
//        while (coll.iterator().hasNext()){
//            System.out.println(coll.iterator().next());
        }
    }
           

remove() 方法與foreach 循環周遊集合元素

Java集合-Collection一、集合架構的概述二、集合架構
Java集合-Collection一、集合架構的概述二、集合架構

代碼實作

public void test3(){
        Collection coll = new ArrayList();
        coll.add(123);coll.add(456);
        coll.add(new Person("Jerry",20));
        coll.add(new String("Tom"));
        coll.add(false);

        //删除集合中"Tom"
        Iterator iterator = coll.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            if("Tom".equals(obj))
                iterator.remove();
        }
        //周遊集合
        iterator = coll.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //foreach周遊集合
        for(Object obj : coll){
            System.out.println(obj);
        }
    }
           

Collection 子接口之一:List 接口

List接口概述:元素有序、且可重複

  • 鑒于 Java 中數組用來存儲資料 的局限性,我們通常使用 List 替代數組
  • List 集合類中 元素有序、且可重複 ,集合中的每個元素都有其對應的順序索引。
  • List 容器中的元素都對應一個整數型的序号記載其在容器中的位置,可以根據序号存取容器中的元素。
  • JDK API 中 List 接口的實作類常用的有: ArrayList 、 LinkedList 和 Vector 。
  • 添加的對象,所在的類要重寫equals()方法
  • Collection接口:單列集合,用來存儲一個一個的對象
    • List接口:存儲有序的、可重複的資料。 -->“動态”數組,替換原有的數組
      • ArrayList:作為List接口的主要實作類;線程不安全的,效率高;底層使用Object[] elementData存儲
      • LinkedList:對于頻繁的插入、删除操作,使用此類效率比ArrayList高;底層使用雙向連結清單存儲
      • Vector:作為List接口的古老實作類;線程安全的,效率低;底層使用Object[] elementData存儲

List接口中的常用方法

  • List 除了從 Collection 集合繼承的方法外, List 集合裡添加了一些根據索引來操作集合元素的 方法 。
  • void add(int index, Object ele):在index位置插入ele元素
  • boolean addAll(int index, Collection eles):從index位置開始将eles中的所有元素添加進來
  • Object get(int index):擷取指定index位置的元素
  • int indexOf(Object obj):傳回obj在集合中首次出現的位置
  • int lastIndexOf(Object obj):傳回obj在目前集合中末次出現的位置
  • Object remove(int index):移除指定index位置的元素,并傳回此元素
  • Object set(int index, Object ele):設定指定index位置的元素為ele
  • List subList(int fromIndex, int toIndex):傳回從fromIndex到toIndex位置的子集合

總結:常用方法

增:add(Object obj)

删:remove(int index) / remove(Object obj)

改:set(int index, Object ele)

查:get(int index)

插:add(int index, Object ele)

長度:size()

周遊:① Iterator疊代器方式

② 增強for循環

List實作類之一: ArrayList

作為List接口的主要實作類;線程不安全的,效率高;底層使用Object[] elementData存儲

ArrayList的分析:

  1. jdk 7情況下 像餓漢式,直接建立一個初始容量為 10 的數組

    ArrayList list = new ArrayList();//底層建立了長度是10的Object[]數組elementData

    list.add(123);//elementData[0] = new Integer(123);

    list.add(11);//如果此次的添加導緻底層elementData數組容量不夠,則擴容。

    預設情況下,擴容為原來的容量的1.5倍,同時需要将原有數組中的資料複制到新的數組中。

    結論:建議開發中使用帶參的構造器:ArrayList list = new ArrayList(int capacity)

  2. jdk 8中ArrayList的變化:ArrayList 像懶漢式,一開始建立一個長度為 0 的數組,當添加第一個元素時再建立一個始容量為 10 的 數組

    ArrayList list = new ArrayList();//底層Object[] elementData初始化為{}.并沒有建立長度為10的數組

    list.add(123);//第一次調用add()時,底層才建立了長度10的數組,并将資料123添加到elementData[0]

    後續的添加和擴容操作與jdk 7 無異。

  3. 小結: jdk7中的ArrayList的對象的建立類似于單例的餓漢式,而jdk8中的ArrayList的對象的建立類似于單例的懶漢式,延遲了數組的建立,節省記憶體。

代碼實作

public void test1(){
        ArrayList list = new ArrayList();
        list.add(123);list.add(456);
        list.add("AA");
        list.add(new Person("Tom",12));
        list.add(456);
        System.out.println(list);//[123, 456, AA, Person{name='Tom', age=12}, 456]

//void add(int index, Object ele):在index位置插入ele元素
        list.add(1,"BB");
        System.out.println(list);//[123, BB, 456, AA, Person{name='Tom', age=12}, 456]        

//boolean addAll(int index, Collection eles):從index位置開始将eles中的所有元素添加進來
        List list1 = Arrays.asList(1, 2, 3);
        list.addAll(list1);
		//list.add(list1);
        System.out.println(list.size());//9

        //Object get(int index):擷取指定index位置的元素
        System.out.println(list.get(0));//123
        
        //int indexOf(Object obj):傳回obj在集合中首次出現的位置。如果不存在,傳回-1.
        int index = list.indexOf(4567);
        System.out.println(index);

		//int lastIndexOf(Object obj):傳回obj在目前集合中末次出現的位置。如果不存在,傳回-1.
        System.out.println(list.lastIndexOf(456));

        //Object remove(int index):移除指定index位置的元素,并傳回此元素
        Object obj = list.remove(0);
        System.out.println(obj);
        System.out.println(list);

        //Object set(int index, Object ele):設定指定index位置的元素為ele
        list.set(1,"CC");
        System.out.println(list);

        //List subList(int fromIndex, int toIndex):傳回從fromIndex到toIndex位置的左閉右開區間的子集合
        List subList = list.subList(2, 4);
        System.out.println(subList);

		//疊代器:方式一Iterator疊代器方式
        Iterator iterator = list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //方式二:增強for循環
        for(Object obj : list){
            System.out.println(obj);
        }

        //方式三:普通for循環
        for(int i = 0;i < list.size();i++){
            System.out.println(list.get(i));
        }

    }
           

List實作類之二: LinkedList

對于頻繁的插入、删除操作,使用此類效率比ArrayList高;底層使用 雙向連結清單 存儲

LinkedList的分析:

LinkedList list = new LinkedList();

内部沒有聲明數組,而是定義了 Node 類型的 first 和 last 用于記錄首末元素。同時,定義内部類,作為 LinkedList 中儲存資料的基

本結構。 Node 除了 儲存資料,還定義了兩個變量:

  • prev 變量記錄前一個元素的位置
  • next 變量記錄下一個元素的 位置

預設值為null

ist.add(123);//将123封裝到Node中,建立了Node對象。

其中,Node定義為:展現了LinkedList的雙向連結清單的說法

Java集合-Collection一、集合架構的概述二、集合架構
private static class Node<E> {
 E item;
 Node<E> next;
 Node<E> prev;

 Node(Node<E> prev, E element, Node<E> next) {
 this.item = element;
 this.next = next;
 this.prev = prev;
 }
 }
           

新增方法

  • void addFirst (Object obj
  • void addLast (Object obj
  • Object getFirst
  • Object getLast
  • Object removeFirst
  • Object removeLast

List實作類之三: Vector

  • Vector 是一個古老的集合, JDK1.0 就有了。大多數操作與 ArrayList相同,差別之處在于 Vector 是線程安全的。
  • 在各種 list 中,最好把 ArrayList 作為預設選擇。當插入、删除頻繁時,

    使用 LinkedList Vector 總是比 ArrayList 慢,是以盡量避免使用。

新增方法:

  • void addElement (Object obj
  • void insertElementAt (Object obj,int index)
  • void setElementAt (Object obj,int index)
  • void removeElement (Object obj
  • void removeAllElements

Vector的源碼分析:jdk7和jdk8中通過Vector()構造器建立對象時,底層都建立了長度為10的數組。在擴容方面,預設擴容為原來的數組長度的2倍。

面試題:ArrayList、LinkedList、Vector三者的異同?談談你的了解? ArrayList 底層是什麼?擴容機制? Vector 和 ArrayList 的最大差別

同:

三個類都是實作了List接口,存儲資料的特點相同:存儲有序的、可重複的資料

不同:

ArrayList:作為List接口的主要實作類;線程不安全的,效率高;底層使用Object[] elementData存儲

LinkedList:線程不安全的,對于頻繁的插入、删除操作,使用此類效率比ArrayList高;底層使用雙向連結清單存儲

Vector:作為List接口的古老實作類;線程安全的,效率低;底層使用Object[] elementData存儲

  • ArrayList 和 LinkedList 的 異同

    二者都線程不安全,相對線程安全的Vector ,執行效率高。

    此外,ArrayList 是實作了基于動态數組的資料結構, LinkedList 基于連結清單的資料結構。對于随機通路 get 和 set ArrayList 覺得優于 LinkedList ,因為 LinkedList 要移動指針。對于新增和删除 操作 add( 特指 插入 和 remove LinkedList 比較占優勢,因為 ArrayList 要移動資料。

  • ArrayList 和 Vector 的差別

    Vector和 ArrayList 幾乎是完全相同的 唯一的差別在于 Vector 是同步類 ( synchronized),屬于強同步類。是以開銷就比 ArrayList 要大,通路要慢。正常情況下 大多數的 Java 程式員使用ArrayList 而不是 Vector, 因為同步完全可以由程式員自己來控制。 Vector 每次擴容請求其大小的 2 倍空間,而 ArrayList 是 1.5 倍。 Vector 還有一個子類 Stack 。

Collection 子接口之二:Set 接口

Set接口概述:存儲無序的、不可重複的資料

Set接口的架構:

  • Collection接口:單列集合,用來存儲一個一個的對象
    • Set接口:存儲無序的、不可重複的資料 -->高中講的“集合”
      • HashSet:作為Set接口的主要實作類;線程不安全的;可以存儲null值
        • LinkedHashSet:作為HashSet的子類;周遊其内部資料時,可以按照添加的順序周遊

          對于頻繁的周遊操作,LinkedHashSet效率高于HashSet.

      • TreeSet:可以按照添加對象的指定屬性,進行排序。

Set接口中沒有額外定義新的方法,使用的都是Collection中聲明過的方法。

要求:向Set(主要指:HashSet、LinkedHashSet)中添加的資料,其所在的類一定要重寫 hashCode() 和 equals()

要求:重寫的 hashCode() 和 equals() 盡可能保持一緻性:相等的對象必須具有相等的散列碼

(重寫兩個方法的小技巧:對象中用作 equals() 方法比較的 Field,都應該用來計算 hashCode 值。)

Set 集合不允許包含相同的元素,如果試把兩個相同的元素加入同一個Set 集合中,則添加操作失敗。

Set 判斷兩個對象是否相同不是使用 == 運算符,而是 根據 equals() 方法

一、Set:存儲無序的、不可重複的資料以HashSet為例說明

無序性:不等于随機性。存儲的資料在底層數組中并非按照數組索引的順序添加,而是根據資料的哈希值決定的。

不可重複性:保證添加的元素按照equals()判斷時,不能傳回true.即:相同的元素隻能添加一個。

二、添加元素的過程:以HashSet為例

我們向HashSet中添加元素a,首先調用元素a所在類的hashCode()方法,計算元素a的哈希值,

此哈希值接着通過某種算法計算出在HashSet底層數組中的存放位置(即為:索引位置),判斷數組此位置上是否已經有元素:

      如果此位置上沒有其他元素,則元素a添加成功。 —>情況1

      如果此位置上有其他元素b(或以連結清單形式存在的多個元素),則比較元素a與元素b的hash值:

            如果hash值不相同,則元素a添加成功。—>情況2

            如果hash值相同,進而需要調用元素a所在類的equals()方法:

                    equals()傳回true,元素a添加失敗

                    equals()傳回false,則元素a添加成功。—>情況3

對于添加成功的情況2和情況3而言:元素a 與已經存在指定索引位置上資料以連結清單的方式存儲。

jdk 7 :元素a放到數組中,指向原來的元素。

jdk 8 :原來的元素在數組中,指向元素a

總結: 7頭插,8尾插    七上八下

HashSet底層:數組+連結清單的結構。

Set實作類之一: HashSet

Java集合-Collection一、集合架構的概述二、集合架構
Java集合-Collection一、集合架構的概述二、集合架構

代碼實作

public void test1(){
        Set set = new HashSet();
        set.add(456);
        set.add(123);
        set.add(123);
        set.add("AA");
        set.add("CC");
        set.add(new User("Tom",12));
        set.add(new User("Tom",12));
        set.add(129);

        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
           

User

public class User implements Comparable{
    private String name;
    private int age;
    public User() {}
    public  User(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;}

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

    @Override
    public boolean equals(Object o) {
        System.out.println("User equals()....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (age != user.age) return false;
        return name != null ? name.equals(user.name) : user.name == null;
    }

    @Override
    public int hashCode() { //return name.hashCode() + age;
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

}

           

Set實作類之二: LinkedHashSet

  • LinkedHashSet 是 HashSet 的子類
  • LinkedHashSet 根據元素的 hashCode 值來決定元素的存儲位置,

    但它 同時使用雙向連結清單 維護元素的次序,這使得元素看起來是以 插入順序儲存 的。

  • LinkedHashSet 插入性能略低于 HashSet 但在疊代通路 Set 裡的全

    部元素時有很好的性能。

  • LinkedHashSet 不允許集合元素重複。
  • LinkedHashSet作為HashSet的子類,在添加資料的同時,每個資料還維護了兩個引用,記錄此資料前一個資料和後一個資料。
  • 優點:對于頻繁的周遊操作,LinkedHashSet效率高于HashSet
    Java集合-Collection一、集合架構的概述二、集合架構

Set實作類之三:TreeSet

  • TreeSet 是 SortedSet 接口的實作類, TreeSet 可以確定集合元素處于排序 狀态。
  • TreeSet 底層使用 紅黑樹 結構存儲資料
  • 新增的方法如下: 了解
  • Comparator comparator
  • Object first()
  • Object last()
  • Object lower(Object e)
  • Object higher(Object e)
  • SortedSet subSet fromElement , toElement
  • SortedSet headSet toElement
  • SortedSet tailSet fromElement
  • TreeSet 兩種排序方法: 自然排序 和 定制排序 。預設情況下, TreeSet 采用自然排序。
Java集合-Collection一、集合架構的概述二、集合架構
  1. 向TreeSet中添加的資料,要求是相同類的對象。因為隻有相同類的兩個執行個體才會比較大小,是以向 TreeSet 中添加的應該是同一個類 的 對象。
  2. 兩種排序方式:自然排序(實作Comparable接口) 和 定制排序(Comparator)
  3. 對于 TreeSet 集合而言,它 判斷兩個對象是否相等的唯一标準 是:兩個對象通過 compareTo (Object obj ) 方法比較 傳回 值。
  4. 自然排序中,比較兩個對象是否相同的标準為:compareTo()傳回0.不再是equals().
public void test1() {
        TreeSet set = new TreeSet();
        //失敗:不能添加不同類的對象
//        set.add(123); set.add("AA");

        set.add(new User("Tom", 12));
        set.add(new User("Jerry", 32));
        set.add(new User("Jim", 2));
        set.add(new User("Mike", 65));
        set.add(new User("Jack", 33));
        set.add(new User("Jack", 56));


        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

    }
           

User

public class User implements Comparable{
    private String name;
    private int age;
    public User() {
    }
    public  User(String name, int age) {
        this.name = name;
        this.age = age;
    }

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


    //按照姓名從大到小排列,年齡從小到大排列
    @Override
    public int compareTo(Object o) {
        if(o instanceof User){
            User user = (User)o;
            int compare = -this.name.compareTo(user.name);
            if(compare != 0){
                return compare;
            }else{
                return Integer.compare(this.age,user.age);
            }
        	}else{
            	throw new RuntimeException("輸入的類型不比對");
        }
    }
}
           
  1. 定制排序中,比較兩個對象是否相同的标準為:compare()傳回0.不再是equals().
public void test2() {
   Comparator com = new Comparator() {
       //按照年齡從小到大排列
       @Override
       public int compare(Object o1, Object o2) {
         if (o1 instanceof User && o2 instanceof User) {
               User u1 = (User) o1;
               User u2 = (User) o2;
               return Integer.compare(u1.getAge(), u2.getAge());
           } else {
               throw new RuntimeException("輸入的資料類型不比對");
           }
       }
   };
//	  在有參數的情況下,按照參數的方式來
      TreeSet set = new TreeSet(com);
      set.add(new User("Tom", 12));
      set.add(new User("Jerry", 32));
      set.add(new User("Jim", 2));
      set.add(new User("Mike", 65));
      set.add(new User("Mary", 33));
      set.add(new User("Jack", 33));
      set.add(new User("Jack", 56));


        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
}
           

周遊Collection的兩種方式

  1. 使用疊代器Iterator
  2. foreach循環(或增強for循環):

    coll.forEach(System.out::println);//java8新特性,方法的引用