Java基礎——ArrayList方法全解(字典版)

hjavn發表於2021-07-30

引言

在使用集合 ArrayList 的時候,經常使用addremove等,其他的沒用過,甚至沒聽說過的還有很多.現在在這個教程中,簡單的瞭解一下,不要求全都記下.相當於在你腦袋裡建一個索引,就是有些方法在用到的時候,不要去重複的造輪子而已.
行了行了.jpg

ArrayList 結構體如下

image.png
包含構造方法總共是33個方法.

開始

以下基於JDK1.8版本,以下方法排名不分先後

ArrayList()

可以使用new ArrayList() 建立一個 ArrayList 集合,如下:

/**
 * 1 簡單的ArrayList
 */
public static ArrayList getArrayList(){
    ArrayList arrayList = new ArrayList();
    arrayList.add("張三");
    arrayList.add("里斯");
    return arrayList;
}

一些編輯器中會報黃線或者淡黃背景提示,如下圖

圖1-1
這個需要給 ArrayList 一個型別,例如 ArrayList<String> .

ArrayList(Collection<? extends E> c)

可以放入一個集合體來初始化 ArrayList,示例程式碼如下:

HashSet<String> temp1 = new HashSet<>();
temp1.add("張三");
temp1.add("里斯");
ArrayList<String> arrayList2 = new ArrayList<>(temp1);
arrayList2.forEach(System.out::println);

ArrayList(int initialCapacity)

構造一個具有指定初始容量的空列表,應用場景就是當你大概知道這個集合儲存的資料量,直接定義好容量,避開集合自增空間浪費資源.

ArrayList<String> arrayList3 = new ArrayList<>(1000);

add() 與 add(int, E)

add()方法是將括號內的值增加到集合末尾.
add(int, E)是將資料插入的具體的下標上,下表從零開始.

ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("張三");
arrayList.add(0,"在天");
arrayList.add("里斯");
arrayList.forEach(System.out::println);

addAll(Collection<? extends E> c)

指集合中的所有元素追加到此列表的末尾;

ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("張三");
arrayList.add("李四");
arrayList.add("王二");
ArrayList<String> arrayList2 = new ArrayList<>();
arrayList2.add("麻子");
arrayList2.add("鐵子");
arrayList.addAll(arrayList2);
System.out.println(arrayList);

輸出:

[張三, 李四, 王二, 麻子, 鐵子]

addAll(int index,Collection<? extends E> c)

相當於是add(int index,E)addAll(Collection<? extends E> c) 結合版
在指定的索引下標,依次追加指定集合中的所有元素.例如上一個例子,我想在張三後面就把麻子鐵子都插隊進去,那麼如下來實現一下.

public static void testAddAllByIndex(){
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    ArrayList<String> arrayList2 = new ArrayList<>();
    arrayList2.add("麻子");
    arrayList2.add("鐵子");
    arrayList.addAll(1,arrayList2);
    System.out.println(arrayList);
}

輸出:

[張三, 麻子, 鐵子, 李四, 王二]

clear()

看名字就應該清楚.從此列表中刪除所有元素.此呼叫返回後,列表將為空,不是Null.

public static void testClear() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    System.out.println("執行 clear() 前,arrayList.size=" + arrayList.size());
    arrayList.clear();
    System.out.println("執行 clear() 後,arrayList.size=" + arrayList.size());
}

輸出:

執行 clear() 前,arrayList.size=3
執行 clear() 後,arrayList.size=0

clone()

在說明這個之前我們先舉一個栗子.
image.png
拷貝物件

public static void testCloneTemp() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    ArrayList<String> arrayList2 = arrayList;
    arrayList.add("混子");
    arrayList2.add("王多魚");
    System.out.println(arrayList2);
}

輸出:

[張三, 李四, 王二, 混子, 王多魚]
我們其實想達到的效果是arrayList2 不要混子,只需要王多魚.但是我們使了=導致了他們兩個的實體地址指向了同一個,這個時候就體現到了clone的重要性.

public static void testClone() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    ArrayList<String> arrayList2 = (ArrayList<String>) arrayList.clone();
    arrayList.add("混子");
    arrayList2.add("王多魚");
    System.out.println(arrayList2);
}

輸出:

[張三, 李四, 王二, 王多魚]
這樣他們就不會互相影響到.

contains(Object o)

列表包含元素o就返回true,否則就返回false;

public static void testContains() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    boolean existMazi = arrayList.contains("麻子");
    boolean existZhangsan = arrayList.contains("張三");
    System.out.printf("存在張三:%s,存在麻子:%s%n", existZhangsan, existMazi);
}

輸出:

存在張三:true,存在麻子:false

ensureCapacity(int size)

變更ArrayList的容量為size.

public static void testChangeCapacity() throws NoSuchFieldException, IllegalAccessException {
    ArrayList<String> arrayList = new ArrayList<>(100);
    int sizeBefore = getCapacity(arrayList);
    arrayList.ensureCapacity(1000);
    int sizeAfter = getCapacity(arrayList);
    System.out.printf("更改前的size=%d,更改後的size=%d", sizeBefore, sizeAfter);
}

輸出:

更改前的size=100,更改後的size=1000
方法getCapacityArrayList獲取容量大小的自定義方法,如下:

public static int getCapacity(ArrayList<?> arrayList) throws NoSuchFieldException, IllegalAccessException {
    Class<ArrayList> arrayListClass = ArrayList.class;
    Field field = arrayListClass.getDeclaredField("elementData");
    field.setAccessible(true);
    Object[] objects = (Object[]) field.get(arrayList);
    return objects.length;
}

forEach 方法遍歷集合

不要在使用forEach的同時使用removeadd 方法, 不然會報異常.
至於為什麼,這裡就不拉開來講了,因為我還沒看懂,搜尋一下後在評論給我講講.

image.png
使用蠻便捷的,就是上面的使用方法,只是不要呼叫新增與刪除的方法就好.

get(int index)

根據下標獲取對應下標的.

public static void testGet(){
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    for (int i = 0; i < arrayList.size(); i++) {
        String valueByIndex = arrayList.get(i);
        System.out.println(valueByIndex);
    }
}

輸出:

張三
李四
王二

indexOf()

根據值獲取對應的下標.

public static void testindexOf() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    System.out.printf("獲取李四的下標:%d%n", arrayList.indexOf("張三"));
    System.out.printf("獲取李四一的下標:%d%n", arrayList.indexOf("李四一"));
}

輸出:

獲取李四的下標:0
獲取李四一的下標:-1

isEmpty()

判斷是否為空集合,空返回true,否則反之返回true.不能用於null.

public static void testIsEmpty() {
    ArrayList<String> arrayList = new ArrayList<>(100);
    System.out.printf("獲取是否為空集合:%s%n", arrayList.isEmpty());
}

輸出:

獲取是否為空集合:true

iterator()

獲取迭代器,使用迭代器遍歷集合.只能使用一次,二次使用需要重新獲取.例如下面程式碼我註釋的地方,再去使用已經沒有效果.

public static void testIterator() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    Iterator<String> iterator = arrayList.iterator();
    while (iterator.hasNext()){
        String str = iterator.next();
        System.out.println(str);
        if("張三".equals(str)){
            iterator.remove();
        }
    }
    // while (iterator.hasNext())
    System.out.println(arrayList);
}

輸出:

張三
李四
[李四]

lastIndexOf(Object o)

返回指定物件在此集合中最後一次出現處的下標.如果找到物件,返回下標,找不到物件就返回-1.

public static void testLastIndexOf() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("張三");
    int lastIndexZs = arrayList.lastIndexOf("張三");//應該返回2
    int lastIndexLsy = arrayList.lastIndexOf("李四一");
    System.out.printf("張三最後出現的下標為:%d,李四一最後出現的下標為:%d%n", lastIndexZs, lastIndexLsy);
}

輸出:

張三最後出現的下標為:2,李四一最後出現的下標為:-1

listIterator()

像是iterator的升級版,可以正逆向遍歷.支援遍歷過程中修改資料,例如setremoveadd.

public static void testListIterator() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    ListIterator<String> listIterator = arrayList.listIterator();
    String firstIndex = listIterator.next();
    System.out.printf("開始刪除:%s,arrayList:%s%n", firstIndex, arrayList);
    listIterator.remove();
    System.out.printf("刪除後,arrayList%s%n" , arrayList);
    listIterator.add("張三");
    listIterator.next();
    listIterator.set("李四替身");
    System.out.printf("set後,arrayList%s%n" , arrayList);
    int prevIndex = listIterator.previousIndex();
    System.out.printf("獲取上一個元素的下標%d%n" , prevIndex);
    listIterator.previous();
    listIterator.set("張三替身");
    System.out.printf("set後,arrayList%s%n" , arrayList);
}

輸出:

開始刪除:張三,arrayList:[張三, 李四]
刪除後,arrayList[李四]
set後,arrayList[張三, 李四替身]
獲取上一個元素的下標1
set後,arrayList[張三, 張三替身]

listIterator(int index)

從指定下標開始遍歷.

public static void testListIteratorStartIndex() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王二");
    // 因法外狂徒張三入獄,只取後面的值
    ListIterator<String> iterator = arrayList.listIterator(1);
    while (iterator.hasNext()) {
        System.out.println(iterator.next());
    }
}

輸出:

李四
王二

remove(int index)

通過下標移除物件,如果進入下標不存在,會出現IndexOutOfBoundsException異常.移除成功會返回物件.

public static void testRemove() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    String removeStr = arrayList.remove(1);
    System.out.println(removeStr);
}

輸出:

李四

remove(Object obj)

移除物件,測試後只會移除第一個匹配的值.移除成功返回true,否之返回false.

public static void testRemoveByObject() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("張三");
    arrayList.add(null);
    System.out.printf("arrayList.remove("張三")返回=%s%n",arrayList.remove("張三"));
    System.out.printf("arrayList=%s%n",arrayList);
}

輸出:

arrayList.remove("張三")返回=true
arrayList=[李四, 張三, null]

removeAll(Collection<?> c)

移除傳入集合中的物件.

public static void testremoveAll() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("張三");
    arrayList.removeAll(new ArrayList<String>() {{
        add("張三");
    }});
    System.out.printf("arrayList=%s%n", arrayList);
}

輸出:

arrayList=[李四]

removeIf()

刪除滿足特定條件的物件.

public static void testRemoveIf() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("張三");
    System.out.printf("刪除張三前,arrayList=%s%n", arrayList);
    arrayList.removeIf("張三"::equals);
    System.out.printf("刪除張三後,arrayList=%s%n", arrayList);
}

輸出:

刪除張三前,arrayList=[張三, 李四, 張三]
刪除張三後,arrayList=[李四]

replaceAll()

替換元素,例如將集合內元素全轉為大寫,或者全部元素進行計算.

public static void testReplaceAll() {
    ArrayList<String> arrayList = new ArrayList<>();
    arrayList.add("張三");
    arrayList.add("李四");
    arrayList.add("王五");
    arrayList.add("趙六");
    arrayList.replaceAll(item -> "姓名:" + item);
    System.out.printf("arrayList=%s%n", arrayList);
}

輸出:

arrayList=[姓名:張三, 姓名:李四, 姓名:王五, 姓名:趙六]

retainAll(Collection<?> c)

取兩個集合的並集,剔除不在兩集合中同時存在的元素;

public static void testRetainAll() {
    ArrayList<String> arrayList = new ArrayList<String>() {{
        add("張三");
        add("李四");
        add("王五");
        add("趙六");
    }};
    arrayList.retainAll(Arrays.asList("王五", "趙六"));
    System.out.printf("arrayList=%s%n", arrayList);
}

輸出:

arrayList=[王五, 趙六]

set(int index, E element)

根據下標替換或者插入物件.
示例,設定集合中下標為1的值為魯班七號.

public static void testSet() {
    ArrayList<String> arrayList = new ArrayList<String>() {{
        add("張三");
        add("李四");
        add("王五");
        add("趙六");
    }};
    System.out.printf("設定前,arrayList=%s%n", arrayList);
    arrayList.set(1,"魯班七號");
    System.out.printf("設定後,arrayList=%s%n", arrayList);
}

方法執行輸出結果為:

設定前,arrayList=[張三, 李四, 王五, 趙六]
設定後,arrayList=[張三, 魯班七號, 王五, 趙六]

size()

返回集合中的資料條數.

sort(Comparator<? super E> c)

對集合內物件進行以指定方式排序.

public static void testSort() {
    ArrayList<Integer> arrayList = new ArrayList<Integer>() {{
        add(100);
        add(200);
        add(40);
        add(80);
    }};
    System.out.printf("排序前,arrayList=%s%n", arrayList);
    arrayList.sort(Comparator.naturalOrder());
    System.out.printf("自然順序排列後,arrayList=%s%n", arrayList);
    arrayList.sort(Comparator.reverseOrder());
    System.out.printf("倒序排列後,arrayList=%s%n", arrayList);
}

方法執行輸出結果為:

排序前,arrayList=[100, 200, 40, 80]
自然順序排列後,arrayList=[40, 80, 100, 200]
倒序排列後,arrayList=[200, 100, 80, 40]

spliterator()

並行迭代器,就是把集合中的物件放到迭代器中.
然後,可以開啟多個執行緒並行處理這些物件.
示例程式碼如下:

public static void testSpliterator() {
    ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));

    Spliterator<Integer> sItr = arrayList.spliterator();
    // 遍歷後迭代器中的值也會消失
    // sItr.forEachRemaining(d -> System.out.print(d));   //123456
    new Thread(() -> {
        for (int i = 0; i < 4; i++) {
            sItr.tryAdvance(d -> System.out.printf("執行緒:%s,搶到了:%d%n", Thread.currentThread().getName(), d));
        }
    }).start();
    new Thread(() -> {
        for (int i = 0; i < 4; i++) {
            sItr.tryAdvance(d -> System.out.printf("執行緒:%s,搶到了:%d%n", Thread.currentThread().getName(), d));
        }
    }).start();
}

方法執行輸出結果為:

執行緒:Thread-0,搶到了:1
執行緒:Thread-0,搶到了:3
執行緒:Thread-0,搶到了:4
執行緒:Thread-0,搶到了:5
執行緒:Thread-1,搶到了:2
執行緒:Thread-1,搶到了:6

subList(int formIndex,int toIndex)

擷取集合的一部分並返回一個List集合.

image.png

圖來自菜鳥教程
示例程式碼如下:

public static void testSubList() {
    ArrayList<String> arrayList = new ArrayList<>(Arrays.asList("p", "r", "o", "g", "r", "a", "m"));
    List<String> subList1 = arrayList.subList(0, 7);
    System.out.printf("arrayList.subList(0,7) result:%s%n", subList1);
    List<String> subList2 = arrayList.subList(3, 7);
    System.out.printf("arrayList.subList(3,7) result:%s%n", subList2);
    List<String> subList3 = arrayList.subList(3, 6);
    System.out.printf("arrayList.subList(3,6) result:%s%n", subList3);
}

方法執行輸出結果為:

arrayList.subList(0,7) result:[p, r, o, g, r, a, m]
arrayList.subList(3,7) result:[g, r, a, m]
arrayList.subList(3,6) result:[g, r, a]

toArray() && toArray(T[] a)

返回一個當前集合順序排列並且包含 ArrayList 中所有元素的陣列.
示例程式碼如下:

public static void testToArray() {
    // 1. toArray()
    ArrayList<Integer> arrayList = new ArrayList<>(Arrays.asList(10, 20, 3, 41, 15, 26));
    Object[] num = arrayList.toArray();
    System.out.println(Arrays.toString(num));
    // 2. toArray(T[] a)
    Integer[] arr = new Integer[arrayList.size()];
    arr = arrayList.toArray(arr);
    System.out.println(Arrays.toString(arr));
}

方法執行輸出結果為:

[10, 20, 3, 41, 15, 26]
[10, 20, 3, 41, 15, 26]

trimToSize()

去除ArrayList多餘的容量.
示例程式碼如下:

public static void testTrimToSize() throws NoSuchFieldException, IllegalAccessException {
    ArrayList<Integer> arrayList = new ArrayList<>(100);
    arrayList.add(11);
    arrayList.add(12);
    arrayList.add(13);
    System.out.printf("trimToSize之前ArrayList容量大小:%d%n", getCapacity(arrayList));
    arrayList.trimToSize();
    System.out.printf("trimToSize之後ArrayList容量大小:%d%n", getCapacity(arrayList));
}

方法執行輸出結果為:

trimToSize之前ArrayList容量大小:100
trimToSize之後ArrayList容量大小:3

寫完遼

不用死記硬背,收藏起來當成字典查一查.
上面程式碼的地址
https://github.com/cuifuan/house/blob/master/src/test/java/com/home/test/TestArrayListFun.java

QQ圖片20171201143204.jpg
告辭!

相關文章