引言
在使用集合 ArrayList
的時候,經常使用add
、remove
等,其他的沒用過,甚至沒聽說過的還有很多.現在在這個教程中,簡單的瞭解一下,不要求全都記下.相當於在你腦袋裡建一個索引,就是有些方法在用到的時候,不要去重複的造輪子而已.
ArrayList 結構體如下
包含構造方法總共是33
個方法.
開始
以下基於JDK1.8版本,以下方法排名不分先後
ArrayList()
可以使用new ArrayList()
建立一個 ArrayList
集合,如下:
/**
* 1 簡單的ArrayList
*/
public static ArrayList getArrayList(){
ArrayList arrayList = new ArrayList();
arrayList.add("張三");
arrayList.add("里斯");
return arrayList;
}
一些編輯器中會報黃線或者淡黃背景提示,如下圖
這個需要給 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()
在說明這個之前我們先舉一個栗子.
拷貝物件
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
方法getCapacity
為ArrayList
獲取容量大小的自定義方法,如下:
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
的同時使用remove
和 add
方法, 不然會報異常.
至於為什麼,這裡就不拉開來講了,因為我還沒看懂,搜尋一下後在評論給我講講.
使用蠻便捷的,就是上面的使用方法,只是不要呼叫新增與刪除的方法就好.
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
的升級版,可以正逆向遍歷
.支援遍歷過程中修改資料,例如set
、remove
、add
.
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
集合.
圖來自菜鳥教程
示例程式碼如下:
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
告辭!