1. 程式人生 > >JAVA中的容器總結

JAVA中的容器總結

1 容器概念

1.1 容器是什麼

在Java當中,如果有一個類專門用來存放其它類的物件,這個類就叫做容器
是將若干性質相同或相近的類物件組合在一起而形成的一個整體

1.2 容器和陣列的區別和聯絡

1.2.1 區別

1.2.1.1 為什麼需要容器

1 陣列的長度難以擴充
2 陣列中資料的型別必須相同
3 陣列只能建立固定長度的物件

1.2.1.2 容器和陣列的操作區別

容器不是陣列,不能通過下標的方式訪問容器中的元素

1.2.2 聯絡


1 陣列的所有功能通過Arraylist容器都可以實現,只是實現的方式不同
2 如果非要將容器當做一個數組來使用,通過toArraylist

方法返回的就是一個數組

1.2.3 陣列Arrays類常用方法總結

  • 排序相關
 public static void sort(int[] a);
 //從小到大排序
 public static void sort(int[] a, int fromIndex, int toIndex);
 //從哪個元素到哪個元素排序,[fromIndex,toIndex),不包括toIndex
 public static void parallelSort(int[] a);
 public static void parallelSort(int[] a, int fromIndex, int
toIndex); //1.8之後對排序做的優化 //Object[] 陣列的排序有些不同 public static void sort(Object[] a); private static void legacyMergeSort(Object[] a); //object[]的sort呼叫的下面的legacyMergeSort,採用的是插入排序,注意legacyMergeSort是private的,外部不能呼叫
  • 二分法
public static int binarySearch(int[] a, int key);
public static int binarySearch(int
[] a, int fromIndex, int toIndex,int key); //注意,Java中個給的二分,只是說這段區間中有沒有,並返回該index,而不是返回第一個出現的位置或者是最後一次出現的位置 //使用二分搜尋法搜尋指定列表,以獲得指定物件。在進行此呼叫之前,必須根據列表元素的自然順序對列表進行升序排序(通過 sort方法) //如果沒有對列表進行排序,則結果是不確定的。如果列表包含多個等於指定物件的元素,則無法保證找到的是哪一個。 //[1] 該搜尋鍵在範圍內,但不是陣列元素,由0開始計數,得“ - 插入點索引值 -1”;舉例搜尋3,陣列[1 2 4] //插入點是指第一個大於該鍵key的元素的索引。 //[2] 該搜尋鍵在範圍內,且是陣列元素,由0開始計數,得搜尋值的索引值;搜尋3 陣列[1 2 3] //[3] 該搜尋鍵不在範圍內,且小於範圍(陣列)內元素,返回–fromIndex - 1;搜尋0 陣列[1 2 3] //[4] 該搜尋鍵不在範圍內,且大於範圍(陣列)內元素,返回 –toIndex - 1。搜尋4 陣列[1 2 3] //運用的時候,一般判斷是否大於0
  • 其他常用
public static boolean equals(int[] a, int[] a2);
//判斷兩個陣列元素是否相等

public static void fill(int[] a, int val);
public static void fill(int[] a, int fromIndex, int toIndex, int val);
//用val填充陣列

public static int[] copyOf(int[] original, int newLength);
//將原陣列拷貝到一個長度為newLength的新陣列中,並返回該陣列,newLength較大就用0填充,小就擷取前一部分
public static int[] copyOfRange(int[] original, int from, int to);
//返回一個從from到to複製的一個數組,length=to-from

public static int hashCode(int a[]);
//返回hashcode
public static String toString(int[] a);
//Arrays.toString(a)非常方便列印陣列元素

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
//Arrays.asList把陣列元素填充到一個List返回

2 容器總結

2.1 容器介面及分類

這裡寫圖片描述
大方向上,主要分為Iterator、Collection、Map、Comparable四大介面

其中Iterator迭代器,設計的目的是在未知容器具體的型別的情況下,用來遍歷容器元素,與foreach一起使用

Comparable介面則用於比較

剩下的容器型別都是繼承了Collection、Map介面
具體劃分下,List、Set、Queue介面繼承Collection介面

2.2 Collection、Map介面方法分析

2.2.1 Collection介面

序列容器,儲存單一的元素

·collection介面的定義方法

向上轉型定義

ArrayList list = new ArrayList();
//普通定義了一個ArrayList類物件

List list = new ArrayList();
Collection con = new ArrayList();
//向上轉型到List或者collection介面
//向上轉型到哪個介面看自己情況,但是new的一定是類,介面是不能new的!!!!!

List<Integer> = new ArrayList<>();
//加了泛型
List<List<Integer>> list = new ArrayList<>();
//List巢狀List的定義new的也是一個ArrayList

//初始化
List<Integer> objList = new ArrayList(Arrays.asList(new Integer[]{1,2,3}));
List<Integer> objList = Arrays.asList(new Integer[]{1,2,3});

·collection介面的遍歷方法

//方法一:
//超級for迴圈遍歷
for(String attribute : list) {
  System.out.println(attribute);
}
//方法二:
//對於ArrayList來說速度比較快, 用for迴圈, 以size為條件遍歷:
for(int i = 0 ; i < list.size() ; i++) {
  system.out.println(list.get(i));
}

//方法三:
//集合類的通用遍歷方式, 從很早的版本就有, 用迭代器迭代
Iterator it = list.iterator();
while(it.hasNext()) {
  System.ou.println(it.next);
}

·collection介面的常見方法

1 單元素的操作

boolean add(Object o);
//將物件新增給集合
//集合呼叫add方法發生改變則返回true
boolean remove(Object o);
//刪除集合中的某一元素
//刪除成功返回true
boolean contains(Object o);
//查詢集合中是否含有元素o
boolean equals(Object o);

2 一個集合的操作

boolean addAll(Collection c);
//新增集合C元素到當前集合
//如果集合呼叫addAll方法而發生更改返回true
//引數c用於指定要將全部元素新增到列表中的collection
boolean removeAll(Collection c);
//從集合中刪除集合c中的所有元素
//如果集合呼叫removeAll方法而發生更改返回true
boolean retainAll(Collection c);
//從集合中刪除集合c中不包含的元素
//如果集合呼叫方法而發生更改返回true
boolean containsAll(Collection c);
//查詢集合中是否含有集合c中的所有元素
//全部包含返回true

3 查詢操作

void clear();
//清空集合
int size();
//返回集合元素個數
int hashCode();
//返回集合的hashcode
boolean isEmpty();
//判斷當前集合是否為空,空為true
Iterator<E> iterator();
//返回一個迭代器,用來訪問集合中的各個元素

4 和陣列之間的轉化

 Object[] toArray();
 //返回一個內含集合所有元素的陣列
 //無需傳入引數,可以直接將集合轉換成Object陣列進行返回,而且也只能返回Object型別

//還有一個過載方法
<T> T[] toArray(T[] a);
//同樣返回一個內含集合所有元素的陣列
//需要傳入一個數組作為引數,並通過泛型T的方式定義引數,所返回的陣列型別就是呼叫集合的泛型,所以自己無需再轉型
//但是根據傳入陣列的長度與集合的實際長度的關係,會有不同的處理
//a:陣列長度不小於集合長度,直接拷貝,不會產生新的陣列物件;
//b:陣列長度小於集合長度,會建立一個與集合長度相同的新陣列,將集合的資料拷貝到新陣列並將新陣列的引用返回。
collection.add(Arrays.asList(array));
//將陣列新增到collection中,這裡返回的是ArrayList
//Arrays.asList方法
//這裡是將整個陣列作為collection的一個元素新增進去的

//如果要將陣列內的元素作為collection的相互獨立的元素新增,就是直接asList()
//但是需要注意的是, Arrays.asList() 返回一個受指定陣列決定的固定大小的列表。所以不能做 add 、 remove 等操作,否則會報錯。
//或者在定義的時候轉換新增
Collection con = new ArrayList(Arrays.asList(array));

·collection介面的分類

  • 1 List介面
    類似於陣列,建立數字索引和物件的關聯,能夠自動擴充容量
    • ArrayList
      類似於動態陣列,適用於大量隨機訪問
      的情況,但插入和刪除的代價非常高昂
    • LinkedList
      類似於連結串列,也提供了優化的順序訪問,在表中間插入和刪除方面代價低廉,隨機訪問代價較高
      添加了可以使其作為棧、佇列、雙端佇列的方法
  • 2 Set介面
    Set不儲存重複的元素,Set具有和Collection完全一樣的介面,沒有額外的功能

    • HashSet
      提供最快的查詢速度

    • TreeSet
      保持元素處於排序狀態

    • LinkedHashSet
      以插入順序儲存元素

  • 3 Queue介面
    佇列是一個典型先進先出(FIFO)的容器,從容器的一端放入事物,從另一端取出,並且事物放入容器的順序和取出的順序是相同的。
    佇列常被當做一種可靠地將物件從程式的某個區域傳入到另一個區域的途徑,在併發程式設計中極為重要。

    • LinkedList
      典型佇列
    • PriorityQueue
      優先順序佇列
      與普通佇列不同,優先佇列每次彈出的是優先順序最高的元素。可以通過提供自己的Comparator來修改

·collection介面內部的互相轉換(包括陣列)

//List 轉 陣列
Object[] result = List.toArray();

//陣列 轉 Set
Set staffsSet = new HashSet(Arrays.asList(array));
//Set 轉 陣列
Object[] result = Set.toArray();
//List 轉 Set
Set result = new HashSet(List);
//Set 轉 List
List result = new ArrayList(set);


所以你看,collection下都可以之間轉化,和陣列之間也都是依賴於toArray()和asList(),但是這裡面asList()有一些必須要注意的地方

·asList()方法的一些坑 (重要)

首先我們來看asList()方法的原始碼

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

這裡返回的ArrayList並不是我們上面collection介面下的ArrayList,而是在Arrays類內定義的一個靜態內部類

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable

同樣需要注意的就是asList方法傳入的引數是泛型T的一個引數a,這個a是類為T的一個物件,是的沒有錯這裡要求是一個*類物件*

那將意味著對於基本資料型別int float char這些構成的陣列int[]只能作為一個類物件處理
原因:int[]陣列內的元素是int,是基本資料型別,而不是類,但是int[] 是一個類,所以a變數作為類引數傳遞時,編譯器認為只傳了一個變數,這個變數的型別是int陣列,所以size為1
但是對於Integer[]來講,裡面每一個元素都是Integer類變數,故每一個元素都能作為list的一個元素

我們看一下對比

int[] i={11,22,33};  
List intList = new ArrayList(Arrays.asList(i));  
//intList中就有一個Integer陣列型別的物件,整個陣列作為一個元素存進去的    
Integer[] ob={11,22,33};  
List<Integer> objList = new ArrayList(Arrays.asList(ob)); 
//數組裡的每一個元素都是作為list中的一個元素  


那麼如何直接根據基本型別的陣列如int[],long[]直接用asList轉成list??
我們可以選擇用apache commons-lang工具包裡的陣列工具類ArrayUtils類的toObject()方法將int[]轉換為Integer[],是Apache提供的class,功能呢強大,要注意導包:

//或者 maven
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.5</version>
    </dependency>
    </dependencies>
Arrays.asList(ArrayUtils.toObject(i));
//上邊的程式碼:int i[]={11,22,33};,達到了我們想要的效果  

不能導包的話,就只能自己遍歷add了

2.2.2 Map介面

Map是一種將物件和物件相關聯的設計

·Map介面的定義方法

和Collection介面一致,向上轉型定義

·Map介面的遍歷方法

//重要的遍歷方法
Set<Map.Entry<K, V>> entrySet();
//這個方法返回的是一個Set<Map.Entry<K,V>>,用於遍歷
for (Map.Entry<String, String> entry : map.entrySet()) {  
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());  
  }  
//Map.Entry 是Map中的一個介面,他的用途是表示一個對映項(裡面有Key和Value),而Set<Map.Entry<K,V>>表示一個對映項的Set。
//Map.Entry裡有相應的getKey、getValue、setValue、equals、hashcode方法

·Map介面的常見方法

int size();
//返回map長度大小
boolean isEmpty();
//判斷map是否為空,空為true
boolean containsKey(Object key);
//判斷map中是否包含key,包含為true
boolean containsValue(Object value);
//判斷map中是否包含value,包含為true

V get(Object key);
//取值
V put(K key, V value);
//存值(k,v)+返回值:若k存在在map中返回原先的舊value,若不存在返回null
V remove(Object key);
//刪除(k,v)+返回值:若k存在在map中返回原先的舊value,若不存在返回null
Set<K> keySet();
//返回map中所有key,是一個set,沒有重複值
Collection<V> values();
//返回map中的所有value,一個collection

void putAll(Map m);
//putAll可以合併兩個MAP,只不過如果有相同的key那麼用後面的覆蓋前面的
void clear();
//清空map

boolean equals(Object o);
//兩個map是否相等
int hashCode();
//map的hashCode

·Map介面的分類

  • HashMap
    用來快速訪問

  • TreeMap
    保持“鍵”始終處於排序狀態

  • LinkedHashMap
    保持元素插入的順序,通過雜湊同樣提供了快速訪問能力