1. 程式人生 > 實用技巧 >Java ArrayList Tutorial with Examples

Java ArrayList Tutorial with Examples

ArrayList in Java is used to store dynamically sized collection of elements. Contrary to Arrays that are fixed in size, an ArrayList grows its size automatically when new elements are added to it.

Java中的ArrayList用於儲存動態調整大小的元素集合。與固定大小的陣列相反,當向其新增新元素時,ArrayList會自動增加其大小

ArrayList is part of Java’s collection framework and implements Java’s List

interface.

ArrayList是Java集合框架的一部分,並實現Java的List介面

Following are few key points to note about ArrayList in Java -

以下是有關Java中ArrayList的幾點注意事項

  • An ArrayList is a re-sizable array, also called a dynamic array. It grows its size to accommodate new elements and shrinks the size when the elements are removed.

    ArrayList是可調整大小的陣列,也稱為動態陣列。它會增加其大小以容納新元素,並在刪除元素時縮小其大小

  • ArrayList internally uses an array to store the elements. Just like arrays, It allows you to retrieve the elements by their index.

    ArrayList在內部使用陣列儲存元素,就像陣列一樣,它允許您按元素索引檢索元素

  • Java ArrayList allows duplicate and null values.

    Java ArrayList 允許重複和空值

  • Java ArrayList is an ordered collection. It maintains the insertion order of the elements.

    Java ArrayList是一個有序集合。它保持元素的插入順序

  • You cannot create an ArrayList of primitive types like int, char etc. You need to use boxed types like Integer, Character, Boolean etc.

    您不能建立基本型別(如int, char等)的ArrayList 您需要裝箱的型別(如Integer, Character, Boolean等)

  • Java ArrayList is not synchronized. If multiple threads try to modify an ArrayList at the same time, then the final outcome will be non-deterministic. You must explicitly synchronize access to an ArrayList if multiple threads are gonna modify it.、

    Java ArrayList不同步。如果多個執行緒嘗試同時修改ArrayList,則最終結果將是不確定的。如果要修改多個執行緒,則必須顯式同步對ArrayList的訪問

Creating an ArrayList and adding new elements to it

建立一個ArrayList並向其中新增新元素

This example shows:

  • How to create an ArrayList using the ArrayList() constructor.

    如何使用ArrayList()建構函式建立ArrayList

  • Add new elements to an ArrayList using the add() method.

    使用add()方法將新元素新增到ArrayList

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;

public class CreateArrayListExample {

    public static void main(String[] args) {

        // Creating an ArrayList of String
        // 建立字串的ArrayList
        List<String> animals = new ArrayList<>();

        // Adding new elements to the ArrayList
        // 向ArrayList中新增新元素
        animals.add("Lion");
        animals.add("Tiger");
        animals.add("Cat");
        animals.add("Dog");

        System.out.println(animals);

        // Adding an element at a particular index in an ArrayList
        // 在ArrayList中的特定索引處新增元素
        animals.add(2, "Elephant");

        System.out.println(animals);
    }
}

Output

[Lion, Tiger, Cat, Dog]
[Lion, Tiger, Elephant, Cat, Dog]

Creating an ArrayList from another collection

從另一個集合建立ArrayList

This example shows:

  • How to create an ArrayList from another collection using the ArrayList(Collection c) constructor.

    如何使用ArrayList(Collection c)建構函式從另一個集合建立ArrayList

  • How to add all the elements from an existing collection to the new ArrayList using the addAll() method.

    如何使用addAll()方法將現有集合中的所有元素新增到新的ArrayList中

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;

public class CreateArrayListFromCollectionExample {

    public static void main(String[] args) {

        List<Integer> firstFivePrimeNumbers = new ArrayList<>();
        firstFivePrimeNumbers.add(2);
        firstFivePrimeNumbers.add(3);
        firstFivePrimeNumbers.add(5);
        firstFivePrimeNumbers.add(7);
        firstFivePrimeNumbers.add(11);

        // Create an ArrayList from another collection
        // 從另一個集合建立一個ArrayList
        List<Integer> firstTenPrimeNumbers = new ArrayList<>(firstFivePrimeNumbers);

        List<Integer> nextFivePrimeNumbers = new ArrayList<>();
        nextFivePrimeNumbers.add(13);
        nextFivePrimeNumbers.add(17);
        nextFivePrimeNumbers.add(19);
        nextFivePrimeNumbers.add(23);
        nextFivePrimeNumbers.add(29);

        // Adding an entries collection to an ArrayList
        // 將整個集合新增到ArrayList
        firstTenPrimeNumbers.addAll(nextFivePrimeNumbers);

        System.out.println(firstTenPrimeNumbers);
    }
}

Output

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

Accessing elements from an ArrayList

從ArrayList訪問元素

This example shows:

  • How to check if an ArrayList is empty using the isEmpty() method.

    如何使用isEmpty()方法檢查ArrayList是否為空

  • How to find the size of an ArrayList using the size() method.

    如何使用size()方法查詢ArrayList的大小

  • How to access the element at a particular index in an ArrayList using the get() method.

    如何使用get()方法訪問ArrayList中特定索引處的元素

  • How to modify the element at a particular index in an ArrayList using the set() method.

    如何使用set()方法修改ArrayList中特定索引處的元素

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;

public class AccessElementsFromArrayListExample {

    public static void main(String[] args) {
        List<String> topCompanies = new ArrayList<>();

        // Check if an ArrayList is empty
        // 檢查ArrayList是否為空
        // topCompanies列表是否為空
        System.out.println("Is the topCompanies list empty? : " + topCompanies.isEmpty());

        topCompanies.add("Google");
        topCompanies.add("Apple");
        topCompanies.add("Microsoft");
        topCompanies.add("Amazon");
        topCompanies.add("Facebook");

        // Find the size of ArrayList
        // 查詢ArrayList的大小
        // 這是世界排名前五的公司
        System.out.println("Here are the top " + topCompanies.size() + " companies in the world");
        System.out.println(topCompanies);

        // Retrieve the element at a given index
        // 給定索引檢查元素
        String bestCompany = topCompanies.get(0);
        String secondBestCompany = topCompanies.get(1);
        String lastCompany = topCompanies.get(topCompanies.size() - 1);

        System.out.println("Best Company: " + bestCompany);
        System.out.println("Second Best Company: " + secondBestCompany);
        System.out.println("Last Company in the list: " + lastCompany);

        // Modify the element at a given index
        // 修改給定索引處的元素
        topCompanies.set(4, "Walmart");
        System.out.println("Modified top companies list: " + topCompanies);
    }
}

Output

Is the topCompanies list empty? : true
Here are the top 5 companies in the world
[Google, Apple, Microsoft, Amazon, Facebook]
Best Company: Google
Second Best Company: Apple
Last Company in the list: Facebook
Modified top companies list: [Google, Apple, Microsoft, Amazon, Walmart]

Removing elements from an ArrayList

從ArrayList中刪除元素

This example shows:

  1. How to remove the element at a given index in an ArrayList | remove(int index)

    如何刪除ArrayList中給定索引處的元素

  2. How to remove an element from an ArrayList | remove(Object o)

    如何從ArrayList中刪除元素

  3. How to remove all the elements from an ArrayList that exist in a given collection | removeAll()

    如何從ArrayList中刪除給定集合中存在的所有元素

  4. How to remove all the elements matching a given predicate | removeIf()

    如何刪除與給定謂詞匹配的所有元素

  5. How to clear an ArrayList | clear()

    如何清除ArrayList

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class RemoveElementsFromArrayListExample {

    public static void main(String[] args) {

        List<String> programmingLanguages = new ArrayList<>();
        programmingLanguages.add("C");
        programmingLanguages.add("C++");
        programmingLanguages.add("Java");
        programmingLanguages.add("Kotlin");
        programmingLanguages.add("Python");
        programmingLanguages.add("Perl");
        programmingLanguages.add("Ruby");

        System.out.println("Initial List: " + programmingLanguages);

        // Remove the element at index 5
        // 刪除索引為5的元素
        programmingLanguages.remove(5);
        System.out.println("After remove(5): " + programmingLanguages);

        // Remove the first occurrence of the given element from the ArrayList
        // 從ArrayList中刪除給定元素的第一次出現的地方
        // (The remove() method returns false if the element does not exist in the ArrayList)
        // (如果ArrayList中不存在該元素,則remove()方法將返回false)
        boolean isRemoved = programmingLanguages.remove("Kotlin");
        System.out.println("After remove(\"Kotlin\"): " + programmingLanguages);

        // Remove all the elements that exist in a given collection
        // 刪除給定集合中存在的所有元素
        List<String> scriptingLanguages = new ArrayList<>();
        scriptingLanguages.add("Python");
        scriptingLanguages.add("Ruby");
        scriptingLanguages.add("Perl");

        programmingLanguages.removeAll(scriptingLanguages);
        System.out.println("After removeAll(scriptingLanguages): " + programmingLanguages);

        // Remove all the elements that satisfy the given predicate
        // 刪除所有滿足給定謂詞的元素
        programmingLanguages.removeIf(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("C");
            }
        });

        /*
            The above removeIf() call can also be written using lambda expression like this -
            programmingLanguages.removeIf(s -> s.startsWith("C"))
            上面的removeIf()呼叫也可以使用lambda表示式編寫,
            programmingLanguages.removeIf(s-> s.startsWith(“ C”))
        */

        System.out.println("After Removing all elements that start with \"C\": " + programmingLanguages);

        // Remove all elements from the ArrayList
        // 從ArrayList中刪除所有元素
        programmingLanguages.clear();
        System.out.println("After clear(): " + programmingLanguages);
    }
}

Output

Initial List: [C, C++, Java, Kotlin, Python, Perl, Ruby]
After remove(5): [C, C++, Java, Kotlin, Python, Ruby]
After remove("Kotlin"): [C, C++, Java, Python, Ruby]
After removeAll(scriptingLanguages): [C, C++, Java]
After Removing all elements that start with "C": [Java]
After clear(): []

Iterating over an ArrayList

遍歷ArrayList

The following example shows how to iterate over an ArrayList using

  1. Java 8 forEach and lambda expression.
  2. iterator().
  3. iterator() and Java 8 forEachRemaining() method.
  4. listIterator().
  5. Simple for-each loop.
  6. for loop with index.
package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class IterateOverArrayListExample {

    public static void main(String[] args) {

        List<String> tvShows = new ArrayList<>();
        tvShows.add("Breaking Bad");
        tvShows.add("Game Of Thrones");
        tvShows.add("Friends");
        tvShows.add("Prison break");

        // 使用Java 8 forEach和lambda進行迭代
        System.out.println("=== Iterate using Java 8 forEach and lambda ===");
        tvShows.forEach(tvShow -> {
            System.out.println(tvShow);
        });

        // 使用iterator()進行迭代
        System.out.println("\n=== Iterate using an iterator() ===");
        Iterator<String> tvShowIterator = tvShows.iterator();
        while (tvShowIterator.hasNext()) {
            String tvShow = tvShowIterator.next();
            System.out.println(tvShow);
        }

        // 使用iterator()和Java 8 forEachRemaining()方法進行迭代
        System.out.println("\n=== Iterate using an iterator() and Java 8 forEachRemaining() method ===");
        tvShowIterator = tvShows.iterator();
        tvShowIterator.forEachRemaining(tvShow -> {
            System.out.println(tvShow);
        });

        // 使用listIterator()進行雙向迭代
        System.out.println("\n=== Iterate using a listIterator() to traverse in both directions ===");
        // Here, we start from the end of the list and traverse backwards.
        // 在這裡,我們從列表的末尾開始並向後移動
        ListIterator<String> tvShowListIterator = tvShows.listIterator(tvShows.size());
        while (tvShowListIterator.hasPrevious()) {
            String tvShow = tvShowListIterator.previous();
            System.out.println(tvShow);
        }

        // 使用簡單的for-each迴圈進行迭代
        System.out.println("\n=== Iterate using simple for-each loop ===");
        for (String tvShow : tvShows) {
            System.out.println(tvShow);
        }

        // 使用帶索引的for迴圈進行迭代
        System.out.println("\n=== Iterate using for loop with index ===");
        for (int i = 0; i < tvShows.size(); i++) {
            System.out.println(tvShows.get(i));
        }
    }
}

Output

=== Iterate using Java 8 forEach and lambda ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== Iterate using an iterator() ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== Iterate using an iterator() and Java 8 forEachRemaining() method ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== Iterate using a listIterator() to traverse in both directions ===
Prison break
Friends
Game Of Thrones
Breaking Bad

=== Iterate using simple for-each loop ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== Iterate using for loop with index ===
Breaking Bad
Game Of Thrones
Friends
Prison break

The iterator() and listIterator() methods are useful when you need to modify the ArrayList while traversing.

當您需要在遍歷時修改ArrayList時,iterator()和listIterator()方法很有用

Consider the following example, where we remove elements from the ArrayList using iterator.remove() method while traversing through it -

考慮以下示例,在該示例中,我們遍歷陣列時使用iterator.remove()方法從ArrayList中刪除了元素

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListIteratorRemoveExample {

    public static void main(String[] args) {

        List<Integer> numbers = new ArrayList<>();
        numbers.add(13);
        numbers.add(18);
        numbers.add(25);
        numbers.add(40);

        Iterator<Integer> numbersIterator = numbers.iterator();
        while (numbersIterator.hasNext()) {
            Integer num = numbersIterator.next();
            if (num % 2 != 0) {
                numbersIterator.remove();
            }
        }

        System.out.println(numbers);
    }
}

Output

[18, 40]

Searching for elements in an ArrayList

在ArrayList中搜索元素

The example below shows how to:

  • Check if an ArrayList contains a given element | contains()

    檢查ArrayList是否包含給定元素

  • Find the index of the first occurrence of an element in an ArrayList | indexOf()

    查詢ArrayList中第一次出現的元素的索引

  • Find the index of the last occurrence of an element in an ArrayList | lastIndexOf()

    查詢ArrayList中最後一次出現的元素的索引

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;

public class SearchElementsInArrayListExample {

    public static void main(String[] args) {

        List<String> names = new ArrayList<>();
        names.add("John");
        names.add("Alice");
        names.add("Bob");
        names.add("Steve");
        names.add("John");
        names.add("Steve");
        names.add("Maria");

        // Check if an ArrayList contains a given element
        // 檢查ArrayList是否包含給定元素
        // 名稱陣列是否包含“鮑勃”?
        System.out.println("Does names array contain \"Bob\"? : " + names.contains("Bob"));

        // Find the index of the first occurrence of an element in an ArrayList
        // 查詢ArrayList中第一次出現的元素的索引
        System.out.println("indexOf \"Steve\": " + names.indexOf("Steve"));
        System.out.println("indexOf \"Mark\": " + names.indexOf("Mark"));

        // Find the index of the last occurrence of an element in an ArrayList
        // 查詢ArrayList中最後一次出現的元素的索引
        System.out.println("lastIndexOf \"John\" : " + names.lastIndexOf("John"));
        System.out.println("lastIndexOf \"Bill\" : " + names.lastIndexOf("Bill"));
    }
}

Output

indexOf "Steve": 3
indexOf "Mark": -1
lastIndexOf "John" : 4
lastIndexOf "Bill" : -1

ArrayList of user defined objects

使用者自定義物件的ArrayList

Since ArrayList supports generics, you can create an ArrayList of any type. It can be of simple types like Integer, String, Double or complex types like an ArrayList of ArrayLists, or an ArrayList of HashMaps or an ArrayList of any user defined objects.

由於ArrayList支援泛型,因此您可以建立任何型別的ArrayList。它可以是簡單型別,例如整數,字串,雙精度型,也可以是複雜型別,例如ArrayLists的ArrayList或HashMaps的ArrayList或任何使用者自定義物件的ArrayList。

In the following example, you’ll learn how to create an ArrayList of user defined objects.

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;

class User {
    private String name;
    private int age;

    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;
    }
}

public class ArrayListUserDefinedObjectExample {

    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("Rajeev", 25));
        users.add(new User("John", 34));
        users.add(new User("Steve",29));

        users.forEach(user -> {
            System.out.println("Name : " + user.getName() + " Age : " + user.getAge());
        });
    }
}

Output

Name : Rajeev Age : 25
Name : John Age : 34
Name : Steve Age : 29

Sorting an ArrayList

排序ArrayList

Sorting an ArrayList is a very common task that you will encounter in your programs. In this section, I’ll show you how to -

對ArrayList進行排序是您在程式中會遇到的非常常見的任務

  • Sort an ArrayList using Collections.sort() method.

    使用Collections.sort()方法對ArrayList進行排序

  • Sort an ArrayList using ArrayList.sort() method.

    使用ArrayList.sort()方法對ArrayList進行排序

  • Sort an ArrayList of user defined objects with a custom comparator.

    使用自定義比較器對使用者定義物件的ArrayList進行排序

1. Sort an ArrayList using Collections.sort() method

使用Collections.sort()方法對ArrayList進行排序

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ArrayListCollectionsSortExample {

    public static void main(String[] args) {

        List<Integer> numbers = new ArrayList<>();
        numbers.add(13);
        numbers.add(7);
        numbers.add(18);
        numbers.add(5);
        numbers.add(2);

        System.out.println("Before : " + numbers);

        // Sorting an ArrayList using Collections.sort() method
        // 使用Collections.sort()方法對ArrayList進行排序
        Collections.sort(numbers);

        System.out.println("After : " + numbers);
    }
}

Output

Before : [13, 7, 18, 5, 2]
After : [2, 5, 7, 13, 18]

2. Sort an ArrayList using ArrayList.sort() method

使用ArrayList.sort()方法對ArrayList進行排序

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class ArrayListSortExample {

    public static void main(String[] args) {

        List<String> names = new ArrayList<>();
        names.add("Lisa");
        names.add("Jennifer");
        names.add("Mark");
        names.add("David");

        System.out.println("Names : " + names);

        // Sort an ArrayList using its sort() method. You must pass a Comparator to the ArrayList.sort() method.
        // 使用其sort()方法對ArrayList進行排序
        // 您必須將Comparator傳遞給ArrayList.sort()方法
        names.sort(new Comparator<String>() {
            @Override
            public int compare(String name1, String name2) {
                return name1.compareTo(name2);
            }
        });

        // The above sort() method call can also be written simply uisng lambda expressin
        // 上面的sort()方法呼叫也可以使用lambda表示式簡單地編寫
        names.sort((name1, name2) -> name1.compareTo(name2));

        // Following is an even more concise solution
        // 以下是更簡潔的解決方案
        names.sort(Comparator.naturalOrder());

        System.out.println("Sorted Names : " + names);
    }
}

Output

Names : [Lisa, Jennifer, Mark, David]
Sorted Names : [David, Jennifer, Lisa, Mark]

3. Sort an ArrayList of Objects using custom Comparator

使用自定義比較器對物件的ArrayList進行排序

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Person {
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

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

public class ArrayListObjectSortExample {

    public static void main(String[] args) {

        List<Person> people = new ArrayList<>();
        people.add(new Person("Sachin", 47));
        people.add(new Person("Chris", 34));
        people.add(new Person("Rajeev", 25));
        people.add(new Person("David", 31));

        System.out.println("Person List : " + people);

        // Sort People by their Age
        // 按年齡對人進行排序
        people.sort((person1, person2) -> {
            return person1.getAge() - person2.getAge();
        });

        // A more concise way of writing the above sorting function
        // 編寫上述排序功能的更簡潔方法
        people.sort(Comparator.comparingInt(Person::getAge));

        // 按年齡排序的列表
        System.out.println("Sorted Person List by Age : " + people);

        // You can also sort using Collections.sort() method by passing the custom Comparator
        // 您還可以通過傳遞自定義Comparator使用Collections.sort()方法進行排序
        Collections.sort(people, Comparator.comparing(Person::getName));
        // 按姓名排序的列表
        System.out.println("Sorted Person List by Name : " + people);
    }
}

Output

Person List : 
[Person{name='Sachin', age=47}, Person{name='Chris', age=34}, Person{name='Rajeev', age=25}, Person{name='David', age=31}]
Sorted Person List by Age : 
[Person{name='Rajeev', age=25}, Person{name='David', age=31}, Person{name='Chris', age=34}, Person{name='Sachin', age=47}]
Sorted Person List by Name :
[Person{name='Chris', age=34}, Person{name='David', age=31}, Person{name='Rajeev', age=25}, Person{name='Sachin', age=47}]

Synchronizing Access to an ArrayList

同步訪問ArrayList

The ArrayList class is not synchronized. If multiple threads try to modify an ArrayList at the same time then the final result becomes not-deterministic because one thread might override the changes done by another thread.

ArrayList類不同步。如果多個執行緒嘗試同時修改ArrayList,則最終結果將變得不確定,因為一個執行緒可能會覆蓋另一執行緒所做的更改。

Example Demonstrating ArrayList’s unpredictable behavior in multi-threaded environments

演示ArrayList在多執行緒環境中的不可預測行為的示例

The following example shows what happens when multiple threads try to modify an ArrayList at the same time.

下面的示例顯示了多個執行緒嘗試同時修改ArrayList時發生的情況

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class UnsafeArrayListExample {

    public static void main(String[] args) throws InterruptedException {

        List<Integer> unsafeArrayList = new ArrayList<>();
        unsafeArrayList.add(1);
        unsafeArrayList.add(2);
        unsafeArrayList.add(3);

        // Create a thread pool of size 10
        // 建立大小為10的執行緒池
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // Create a Runnable task that increments each element of the ArrayList by one
        // 建立一個Runnable任務,將ArrayList的每個元素加1
        Runnable task = () -> {
            incrementArrayList(unsafeArrayList);
        };

        // Submit the task to the executor service 100 times.
        // 將任務提交給執行者服務100次
        // All the tasks will modify the ArrayList concurrently
        // 所有任務將同時修改ArrayList
        for(int i = 0; i < 100; i++) {
            executorService.submit(task);
        }

        executorService.shutdown();
        executorService.awaitTermination(60, TimeUnit.SECONDS);

        System.out.println(unsafeArrayList);
    }

    // Increment all the values in the ArrayList by one
    // 將ArrayList中的所有值加1
    private static void incrementArrayList(List<Integer> unsafeArrayList) {
        for(int i = 0; i < unsafeArrayList.size(); i++) {
            Integer value = unsafeArrayList.get(i);
            unsafeArrayList.set(i, value + 1);
        }
    }
}

Output

[99, 100, 100]

Try running the above program multiple times and see how it produces different outputs. To learn more about such issues in multi-threaded programs, check out my article on Java Concurrency Issues and Thread Synchronization.

嘗試多次執行上面的程式,看看它如何產生不同的輸出。要了解有關多執行緒程式中此類問題的更多資訊,請檢視我有關Java併發問題和執行緒同步的文章

Example demonstrating how to synchronize concurrent modifications to an ArrayList

演示如何將併發修改同步到ArrayList的示例

All right! Now let’s see how we can synchronize access to the ArrayList in multi-threaded environments.

現在,讓我看一下如何在多執行緒環境中同步對ArrayList的訪問

The following example shows the synchronized version of the previous example. Unlike the previous program, the output of this program is deterministic and will always be the same.

以下示例顯示了上一示例的同步版本。與以前的程式不同,該程式的輸出是確定性的,並且將始終相同

package com.callicoder.arraylist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class SynchronizedArrayListExample {

    public static void main(String[] args)  throws InterruptedException {

        List<Integer> safeArrayList = Collections.synchronizedList(new ArrayList<>());
        safeArrayList.add(1);
        safeArrayList.add(2);
        safeArrayList.add(3);

        // Create a thread pool of size 10
        // 建立大小為10的執行緒池
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // Create a Runnable task that increments each element of the ArrayList by one
        // 建立一個Runnable任務,將ArrayList的每個元素加1
        Runnable task = () -> {
            incrementArrayList(safeArrayList);
        };

        // Submit the task to the executor service 100 times.
        // 將任務提交給執行者服務100次。
        // All the tasks will modify the ArrayList concurrently
        // 所有任務將同時修改ArrayList
        for (int i = 0; i < 100; i++) {
            executorService.submit(task);
        }

        executorService.shutdown();
        executorService.awaitTermination(60, TimeUnit.SECONDS);

        System.out.println(safeArrayList);
    }

    // Increment all the values in the ArrayList by one
    // 將ArrayList中的所有值加1
    private static void incrementArrayList(List<Integer> safeArrayList) {

        synchronized (safeArrayList) {

            for (int i = 0; i < safeArrayList.size(); i++) {
                Integer value = safeArrayList.get(i);
                safeArrayList.set(i, value + 1);
            }
        }
    }
}

Output

[101, 102, 103]

The above example uses Collections.synchronizedList() method to get a synchronized view of the ArrayList.

上面的示例使用Collections.synchronizedList()方法獲取ArrayList的同步檢視

Moreover, the modifications to the ArrayList inside the incrementArrayList() method is wrapped inside a synchronized block. This ensures that no two threads can increment ArrayList elements at the same time.

此外,對incrementArrayList()方法中對ArrayList的修改被包裝在一個同步塊中。這樣可以確保沒有兩個執行緒可以同時增加ArrayList元素

You can also use a CopyOnWriteArrayList if you need thread safety. It is a thread-safe version of the ArrayList class. It implements all the mutating operations by making a fresh copy of the ArrayList.

如果需要執行緒安全,也可以使用CopyOnWriteArrayList。它是ArrayList類的執行緒安全版本。它通過製作ArrayList的新副本來實現所有的變異操作

Conclusion

In this article, you learned what is an ArrayList, how to create an ArrayList, how to add, modify and remove elements from an ArrayList, how to iterate over an ArrayList, how to sort an ArrayList, and how to synchronize access to an ArrayList.

在本文中,您學習了什麼是ArrayList,如何建立ArrayList,如何在ArrayList中新增,修改和刪除元素,如何在ArrayList上進行迭代,如何對ArrayList進行排序以及如何同步對ArrayList的訪問

Thank you for reading. See you in the next post.