jopa

Java ArrayList类
Java ArrayList类Java编程基础中的ArrayList用于存储动态大小的元素集合。与大小固定的数组相...
扫描右侧二维码阅读全文
28
2019/06

Java ArrayList类

Java ArrayList类

Java编程基础中的ArrayList用于存储动态大小的元素集合。与大小固定的数组相反,ArrayList会在添加新元素时自动增大其大小。

ArrayList是Java集合框架的一部分,它实现了Java的List接口。
以下几点需要注意Java中的ArrayList

  • ArrayList是一个可调整大小的数组,也称为动态数组。它的尺寸越来越大,以适应新的元素,并在元素被移除时缩小尺寸。
  • ArrayList内部使用数组来存储元素。就像数组一样,它允许您通过索引来检索元素。
  • Java ArrayList允许重复值和空值。
  • Java ArrayList是一个有序的集合。它维护元素的插入顺序。
  • 您不能创建原始类型,如一个ArrayList int,chat等你需要用盒装的类型,如Integer,Character,Boolean等。
  • Java ArrayList不同步。如果多个线程同时尝试修改ArrayList,那么最终结果将是非确定性的。如果多个线程要修改它,你必须显式同步对ArrayList的访问。

创建一个ArrayList并添加新的元素

这个例子显示:

  • 如何使用ArrayList()构造函数创建ArrayList 。
  • 使用该add()方法向ArrayList添加新元素。
import java.util.ArrayList;
import java.util.List;

public class CreateArrayListExample {

    public static void main(String[] args) {
        // Creating an ArrayList of String
        List<String> animals = new ArrayList<>();

        // Adding new elements to the ArrayList
        animals.add("Lion");
        animals.add("Tiger");
        animals.add("Cat");
        animals.add("Dog");

        System.out.println(animals);

        // 在ArrayList的特定索引处添加元素
        animals.add(2, "Elephant");

        System.out.println(animals);

    }
}

输出

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

从另一个集合创建一个ArrayList

这个例子显示:

  • 如何使用ArrayList(Collection c)构造函数从另一个ArrayList创建一个ArrayList 。
  • 如何使用该addAll()方法将现有ArrayList中的所有元素添加到新的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);

        // 从另一个集合创建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);

        // 将整个集合添加到ArrayList
        firstTenPrimeNumbers.addAll(nextFivePrimeNumbers);

        System.out.println(firstTenPrimeNumbers);
    }
}

输出:

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

访问ArrayList中的元素

这个例子显示:

  • 如何使用该isEmpty()方法检查ArrayList是否为空。
  • 如何使用该size()方法找到ArrayList的大小。
  • 如何使用该get()方法访问ArrayList中特定索引处的元素。
  • 如何使用该set()方法修改ArrayList中特定索引处的元素。
import java.util.ArrayList;
import java.util.List;

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

        // 检查ArrayList是否为空
        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");

        // 查看ArrayList的大小
        System.out.println("Here are the top " + topCompanies.size() + " companies in the world");
        System.out.println(topCompanies);

        // 查看索引中的元素
        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);

        // 修改指定索引中的元素
        topCompanies.set(4, "Walmart");
        System.out.println("Modified top companies list: " + topCompanies);
    }
}

输出:

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]

从ArrayList中移除元素

这个例子显示:

  • 如何删除ArrayList |中给定索引处的元素 remove(int 索引)
  • 如何从ArrayList |中删除元素 remove(Object o)
  • 如何从ArrayList中移除所有元素| removeAll()
  • 如何删除所有匹配给定谓词|的元素 removeIf()
  • 如何清除ArrayList | clear()
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);

        // 删除索引'5'处的元素
        programmingLanguages.remove(5);
        System.out.println("After remove(5): " + programmingLanguages);

        // 删除元素“Kotlin”(如果元素在ArrayList中不存在,Remove()方法返回false)
        boolean isRemoved = programmingLanguages.remove("Kotlin");
        System.out.println("After remove(\"Kotlin\"): " + programmingLanguages);

        // 删除属于集合脚本语言的所有元素
        List<String> scriptingLanguages = new ArrayList<>();
        scriptingLanguages.add("Python");
        scriptingLanguages.add("Ruby");
        scriptingLanguages.add("Perl");

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

        // 删除满足条件的所有元素
        programmingLanguages.removeIf(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("C");
            }
        });

        /*
            上面的removeIf()调用也可以使用这样的lambda表达式来编写
            programmingLanguages.removeIf(s -> s.startsWith("C"));
        */

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

        // 从ArrayList中删除所有元素
        programmingLanguages.clear();
        System.out.println("After clear(): " + programmingLanguages);
    }
}

迭代ArrayList

以下示例显示如何使用迭代遍历ArrayList
1、Java 8 forEach循环。
2、iterator()。
3、iterator()和Java 8 forEachRemaining()方法。
4、listIterator()。
5、每个循环都很简单。
6、用索引循环。

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");

        System.out.println("=== 使用Java 8 forEach循环进行迭代 ===");
        tvShows.forEach(tvShow -> {
            System.out.println(tvShow);
        });

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

        System.out.println("\n=== 使用iterator()和Java 8 forEachRemaining()方法进行迭代 ===");
        tvShowIterator = tvShows.iterator();
        tvShowIterator.forEachRemaining(tvShow -> {
            System.out.println(tvShow);
        });

        System.out.println("\n=== 使用listIterator()遍历两个方向 ===");
        // 在这里,我们从列表的末尾开始向后遍历。
        ListIterator<String> tvShowListIterator = tvShows.listIterator(tvShows.size());
        while (tvShowListIterator.hasPrevious()) {
            String tvShow = tvShowListIterator.previous();
            System.out.println(tvShow);
        }

        System.out.println("\n=== 使用简单的for循环进行迭代 ===");
        for(String tvShow: tvShows) {
            System.out.println(tvShow);
        }

        System.out.println("\n=== 使用带索引的for循环进行迭代 ===");
        for(int i = 0; i < tvShows.size(); i++) {
            System.out.println(tvShows.get(i));
        }
    }
}

输出:

=== 使用Java 8 forEach循环进行迭代 ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== 使用iterator()进行迭代 ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== 使用iterator()和Java 8 forEachRemaining()方法进行迭代 ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== 使用listIterator()遍历两个方向 ===
Prison break
Friends
Game Of Thrones
Breaking Bad

=== 使用简单的for循环进行迭代 ===
Breaking Bad
Game Of Thrones
Friends
Prison break

=== 使用带索引的for循环进行迭代 ===
Breaking Bad
Game Of Thrones
Friends
Prison break

在遍历期间需要修改ArrayList时,iterator()listIterator()方法很有用。

考虑下面的例子,在iterator.remove()遍历它的时候我们使用方法从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);
    }
}

输出:

[18, 40]

在ArrayList中搜索元素

  • 检查ArrayList是否包含给定的元素| contains()
  • 查找ArrayList中第一次出现元素的索引 indexOf()
  • 查找ArrayList中最后一次出现元素的索引 lastIndexOf()
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");

        // 检查ArrayList是否包含给定的元素
        System.out.println("Does names array contain \"Bob\"? : " + names.contains("Bob"));

        // 查找ArrayList中元素第一次出现的索引
        System.out.println("indexOf \"Steve\": " + names.indexOf("Steve"));
        System.out.println("indexOf \"Mark\": " + names.indexOf("Mark"));

        // 查找ArrayList中元素最后一次出现的索引
        System.out.println("lastIndexOf \"John\" : " + names.lastIndexOf("John"));
        System.out.println("lastIndexOf \"Bill\" : " + names.lastIndexOf("Bill"));
    }
}

输出:

Does names array contain "Bob"? : true
indexOf "Steve": 3
indexOf "Mark": -1
lastIndexOf "John" : 4
lastIndexOf "Bill" : -1

用户定义对象的ArrayList

由于ArrayList支持泛型,因此可以创建任何类型的ArrayList 。它可以是简单的类型,如Integer,String,Double或复杂类型等的ArrayLists的ArrayList,或包含HashMap的ArrayList或任何用户定义的对象的ArrayList。

在以下示例中,您将学习如何创建用户定义对象的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());
        });
    }
}

输出:

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

排序ArrayList

对ArrayList进行排序是您在程序中遇到的一个非常常见的任务。在本节中,我会告诉你如何 -

  • 使用Collections.sort()方法对ArrayList进行排序。
  • 使用ArrayList.sort()方法对ArrayList进行排序。
  • 用自定义比较器对用户定义对象的ArrayList进行排序。

1.使用Collections.sort()方法对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);

        // 使用Collections.sort()方法对ArrayList排序
        Collections.sort(numbers);

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

2.使用ArrayList.sort()方法对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()方法对ArrayList排序。必须将比较器传递给ArrayList.sort()方法。
        names.sort(new Comparator<String>() {
            @Override
            public int compare(String name1, String name2) {
                return name1.compareTo(name2);
            }
        });

        // 上面的' sort() '方法调用也可以简单地使用lambda表达式编写
        names.sort((name1, name2) -> name1.compareTo(name2));

        // 下面是一个更简洁的解决方案
        names.sort(Comparator.naturalOrder());

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

输出:

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

3.使用自定义比较器对对象的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 "{" +
                "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);

        // 按年龄分类
        people.sort((person1, person2) -> {
            return person1.getAge() - person2.getAge();
        });

        // 以上排序函数的一种更简洁的写法
        people.sort(Comparator.comparingInt(Person::getAge));

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

        // 还可以通过传递自定义比较器,使用Collections.sort()方法进行排序
        Collections.sort(people, Comparator.comparing(Person::getName));
        System.out.println("Sorted Person List by Name : " + people);
    }
}

输出:

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

同步对ArrayList的访问

ArrayList类不同步。如果多个线程同时尝试修改一个ArrayList,那么最终的结果变得不确定,因为一个线程可能会覆盖另一个线程所做的更改。

示例演示ArrayList在多线程环境中的不可预知行为
以下示例显示了当多个线程同时尝试修改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);

        // 创建一个大小为10的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // 创建一个可运行任务,将ArrayList中的每个元素递增1
        Runnable task = () -> {
            incrementArrayList(unsafeArrayList);
        };

        // 将任务提交给executor服务100次。
        // 所有的任务都将同时修改ArrayList
        for(int i = 0; i < 100; i++) {
            executorService.submit(task);
        }

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

        System.out.println(unsafeArrayList);
    }

    // 将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);
        }
    }
}

上述程序的最终输出应该相等,[101, 102, 103]因为我们将ArrayList中的值增加了100次。但是如果你运行这个程序,它会在每次运行时产生不同的输出
输出:

[96, 96, 98]

演示如何将并发修改同步到ArrayList的示例

好吧!现在让我们看看我们如何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);

        // 创建一个大小为10的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        // 创建一个可运行任务,将ArrayList中的每个元素递增1
        Runnable task = () -> {
            incrementArrayList(safeArrayList);
        };

        // 将任务提交给executor服务100次。
        // 所有的任务都将同时修改ArrayList
        for(int i = 0; i < 100; i++) {
            executorService.submit(task);
        }

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

        System.out.println(safeArrayList);
    }

    // 将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);
            }
        }
    }
}

输出:

[101, 102, 103]

以上示例使用Collections.synchronizedList()方法来获取ArrayList的同步视图。

而且,对incrementArrayList()方法内的ArrayList的修改被封装在一个synchronized块中。这确保了两个线程不能同时增加ArrayList元素。

CopyOnWriteArrayList如果你需要线程安全,你也可以使用。它是ArrayList类的线程安全版本。它通过创建ArrayList的新副本来实现所有的变异操作。

最后修改:2019 年 06 月 28 日 11 : 26 AM
如果觉得我的文章对你有用,请随意赞赏

发表评论