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

简介: ArrayList 方法字典,可用来日常天天见.不用死记硬背,只需要用到的时候知道有这个东西即可.防止重复造轮子...

引言

在使用集合 ArrayList 的时候,经常使用addremove等,其他的没用过,甚至没听说过的还有很多.现在在这个教程中,简单的了解一下,不要求全都记下.相当于在你脑袋里建一个索引,就是有些方法在用到的时候,不要去重复的造轮子而已.
行了行了.jpg

ArrayList 结构体如下

image.png
包含构造方法总共是33个方法.

开始

以下方法排名不分先后

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
告辞!

相关文章
|
14天前
|
Java 索引 容器
Java ArrayList扩容的原理
Java 的 `ArrayList` 是基于数组实现的动态集合。初始时,`ArrayList` 底层创建一个空数组 `elementData`,并设置 `size` 为 0。当首次添加元素时,会调用 `grow` 方法将数组扩容至默认容量 10。之后每次添加元素时,如果当前数组已满,则会再次调用 `grow` 方法进行扩容。扩容规则为:首次扩容至 10,后续扩容至原数组长度的 1.5 倍或根据实际需求扩容。例如,当需要一次性添加 100 个元素时,会直接扩容至 110 而不是 15。
Java ArrayList扩容的原理
|
14天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
55 4
|
25天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
45 17
|
18天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
19天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
35 2
|
27天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3
|
27天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
17 2
|
27天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
17 1
|
27天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
32 1
|
27天前
|
Java
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅
在Java多线程编程中,`wait()`和`notify()`方法的相遇如同一场奇妙的邂逅。它们用于线程间通信,使线程能够协作完成任务。通过这些方法,生产者和消费者线程可以高效地管理共享资源,确保程序的有序运行。正确使用这些方法需要遵循同步规则,避免虚假唤醒等问题。示例代码展示了如何在生产者-消费者模型中使用`wait()`和`notify()`。
25 1
下一篇
无影云桌面