List简介


List 接口继承自 Collection,在上一章 Java 容器 中已经介绍过,List 接口在 Collection 的基础上添加了大量的方法,使得可以在 List 的中间插入和移除元素。List 有两种类型:

  • ArrayList,它随机访问元素速度较快,但是在 List 的中间插入和移除元素时较慢;
  • LinkedList,它可以以较低的代价在 List 中间进行插入和删除操作,提供了优化的顺序访问,LinkedList 在随机访问方面相对较慢,总体说来,LinkedList 包含的特性要多于 ArrayList。

ArrayList

ArrayList 实现了 List 接口,可以当做一个可扩充尺寸的数组,使用比较简单,通过 add() 方法添加元素,然后通过 get() 方法获取元素:

public class ArrayListTest {

    public static void main(String[] args) {
        //创建 list 对象(向上转型)
        List<Pet> list = new ArrayList<>();
        //添加元素
        list.add(new Cat());
        list.add(new Dog());
        //遍历集合并打印
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i).getName());
        }
    }
}

class Cat extends Pet {
    public String getName() {
        return "Tom";
    }
}

class Dog extends Pet {
    public String getName() {
        return "Sam";
    }
}

class Pet {
    public String getName() {
        return "Pet";
    }
}

上面的例子通过 ArrayList 向上转型来创建一个 List 对象,其中尖括号括起来的就是类型参数,它指定了这个 list 容器可以保存的元素类型,通过使用泛型,就可以在编译器防止将错误类型的对象放置在容器中

当指定了某个类型作为泛型参数时,不仅可以将该类型的对象放置在容器中,也可以将该类型的子类型对象放置在容器中。比如上例中声明的是 Pet 类型,却可以放进 Cat 和 Dog 对象,因为 Cat 和 Dog 继承了 Pet 类。如果没有声明泛型,那么就默认类型为 Object,可以放任何类型的对象

我们接着来看看 ArrayList 的其它操作:

public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        //集合的数值范围 100 ~ 109
        for(int i = 100; i < 110; i++){
            list1.add(i);
        }
        System.out.println("list1: " + list1);
        System.out.println("100 的下标:" + list1.indexOf(101));
        System.out.println("删掉第 0 个元素: " + list1.remove(0));
        //截取前五个元素作为一个新的集合
        List<Integer> list2 = list1.subList(0, 5);
        System.out.println("新的集合 list2:" + list2);
        System.out.println("list1 是否包含 list2: " + list1.containsAll(list2));
        //将集合顺序打乱
        Collections.shuffle(list2);
        System.out.println("打乱顺序后的集合:" + list2);
        //将集合重新排序
        Collections.sort(list2);
        System.out.println("排序后的集合: " + list2);
        //交集操作
        list2.retainAll(list1);
        System.out.println("list1 和 list2 的交集:" + list2);
        //在下标为 2 的位置加一个集合
        list2.addAll(2, list2);
        System.out.println("在下标为 2 的位置加一个集合:" + list2);
        //清空集合
        list2.clear();
        System.out.println("清空集合:" + list2);
    }

打印结果:

list1: [100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
100 的下标:1
删掉第 0 个元素: 100
新的集合 list2:[101, 102, 103, 104, 105]
list1 是否包含 list2: true
打乱顺序后的集合:[105, 103, 102, 104, 101]
排序后的集合: [101, 102, 103, 104, 105]
list1 和 list2 的交集:[101, 102, 103, 104, 105]
在下标为 2 的位置加一个集合:[101, 102, 101, 102, 103, 104, 105, 103, 104, 105]
清空集合:[]

  • List 在创建之后,可以通过 indexOf() 方法来获取某个元素下标;
  • remove() 方法用来删除某个下标的元素;
  • subList() 方法可以从某个集合中创建出一个片段作为一个新的集合,而将这个心机和传递给较大的集合的 containsAll() 方法时,结果肯定为 true;
  • 代码中还引用了 Collections.shuffle() 方法用来打乱集合顺序,用 Collections.sort()
    方法来对集合重新排序;
  • retainAll() 方法是一种有效的交集操作,用来获取两个集合的交集;
  • addAll() 方法可以在集合的中间插入一个新的集合,这对于 ArrayList 来说,代价较高;
  • clear() 方法用来清空集合中的所有元素。

LinkedList

LinkedList 和 ArrayList 一样,也实现了 List 接口,它在 List 中间插入或者移除元素的时候比 ArrayList 更高效,但是随即访问操作的时候要慢一些。LinkedList 还添加了可以使用其作栈、队列或双端队列的方法。

public static void main(String[] args) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        for (int i = 100; i < 110; i++) {
            linkedList.add(i);
        }
        //集合为空时,以下两个方法报错
        System.out.println("第一个元素: " + linkedList.getFirst());
        System.out.println("第一个元素: " + linkedList.element());
        //集合为空时,返回 null
        System.out.println("第一个元素: " + linkedList.peek());
        //集合为空时,以下两个方法报错
        System.out.println("移除第一个元素:" + linkedList.removeFirst());
        System.out.println("移除第一个元素:" + linkedList.remove());
        //集合为空时,返回 null
        System.out.println("移除第一个元素:" + linkedList.poll());
        linkedList.addFirst(1);
        System.out.println("在列表前部插入元素:" + linkedList);
        linkedList.add(2);
        System.out.println("在列表末尾插入元素:" + linkedList);
        linkedList.addLast(3);
        System.out.println("在列表末尾插入元素:" + linkedList);
        linkedList.removeLast();
        System.out.println("删除列表末尾的元素:" + linkedList);
    }

打印结果:

第一个元素: 100
第一个元素: 100
第一个元素: 100
移除第一个元素:100
移除第一个元素:101
移除第一个元素:102
在列表前部插入元素:[1, 103, 104, 105, 106, 107, 108, 109]
在列表末尾插入元素:[1, 103, 104, 105, 106, 107, 108, 109, 2]
在列表末尾插入元素:[1, 103, 104, 105, 106, 107, 108, 109, 2, 3]
删除列表末尾的元素:[1, 103, 104, 105, 106, 107, 108, 109, 2]

LinkedList 中,getFirst() 和 element() 方法完全一样,都是返回列表的头元素,并且不移除它,如果集合为空,那么抛出 NoSuchElementException 异常,peek() 方法也是获取头元素,但是与前面两个方法稍有差异,它在列表为空的时候返回 null。

removeFirst() 和 remove() 方法也是完全一样,移除并且返回列表的头元素,当列表为空的时候,抛出 NoSuchElementException 异常,poll() 方法也是效果一样,但是列表为空时返回 null。

addFirst() 方法是在列表最前面插入元素,add() 和 addLast() 方法效果一样,是在列表末尾插入元素。removeLast() 方法删除并返回列表的最后一个元素。

小结

本文介绍了 List 接口的两个常用的实现类 ArrayListLinkedList 和它们各自的特点,并通过代码示例简要介绍了这两种集合的常用方法。

欢迎关注公众号:一盐难进

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值