Java的编程之旅46——List集合

1.List集合的特殊方法

List接口是Collection接口的子接口,提供了一系列操作元素的方法。 常见的List集合实现类有ArrayList和LinkedList。ArrayList我们在前面已经介绍过了,这一章中着重介绍一下List集合的特有方法。

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        list.add(3,"hahaha"); //通过索引增加元素

        System.out.println(list.remove(3)); //通过索引移除元素,并返回被移除的元素

        System.out.println(list.set(1,"c++"));  //用set函数通过索引修改元素,并返回修改前的元素

        System.out.println(list.get(2));        //用get函数通过索引获取元素,并返回获取到元素的值

        System.out.println(list);

1.增加元素

list.add(index,element) 方法增加元素

2.删除元素

list.remove(index)

3.修改元素

list.set(index,element)

4.获取元素

list.get(index)

2.遍历元素

1.for循环遍历

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

2.foreach遍历

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        //法二foreach
        for (String li :
                list) {
            System.out.println(li);
        }
        

3.迭代器

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

该代码段使用ArrayList和Iterator来遍历列表中的元素并打印出来。 首先,代码创建了一个ArrayList对象,并向其中添加了三个字符串元素("hello","java"和"world")。 然后,通过调用list的iterator()方法获取一个Iterator对象。Iterator是一个接口,用于遍历集合中的元素。 接下来,使用while循环和Iterator的hasNext()方法来检查是否还有下一个元素可遍历。 在循环的每次迭代中,使用Iterator的next()方法获取下一个元素,并将其打印出来。 最终,循环结束后,所有元素都被遍历并打印出来。输出结果为: hello java world

4.stream流

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        list.stream().forEach(System.out::println);

通过调用list的stream()方法获取一个流(Stream)对象。流是Java 8中引入的一种处理集合数据的方式。 接下来,使用Stream的forEach()方法来迭代每个元素,并使用System.out::println方法引用来打印每个元素。 最终,所有元素都被遍历并打印出来。输出结果为: hello java world

5.lambda表达式

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("java");
        list.add("world");

        list.forEach(System.out::println);

使用List的forEach()方法来循环遍历列表中的每个元素。 在forEach()方法中,我们使用System.out::println方法引用来打印每个元素。 最终,所有元素都被遍历并打印出来。输出结果为: hello java world

3.listIterator迭代器

与普通迭代器Iterator相比,listIterator提供了更多的功能。它可以向前和向后遍历集合中的元素,还可以修改集合中的元素,以及获取当前元素的索引。

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("JavaSE");
        list.add("MYSQL");
        list.add("JavaWeb");
        list.add("JavaEE");
        ListIterator<String> lt = list.listIterator();
        while (lt.hasNext()){        //正向遍历
            System.out.println(lt.next());
        }

        while (lt.hasPrevious()){
            System.out.println(lt.next());  //逆向遍历
        }

4. 并发性修改异常

并发性修改异常(ConcurrentModificationException)是Java集合框架中的一种异常,表示在迭代器遍历集合元素时,发生了结构性修改。结构性修改指的是改变集合大小或使迭代器失效的操作,如添加、删除或修改元素。

在Java集合框架中,有一些迭代器是通过快速失败机制实现的。这意味着如果在迭代器遍历集合期间进行了结构性修改,会立即抛出ConcurrentModificationException异常,而不是继续遍历。这是为了避免在并发环境下可能出现的不一致性和数据损坏。

例: 在一组列表里增加元素

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("JavaSE");
        list.add("MYSQL");
        list.add("JavaWeb");
        list.add("JavaEE");
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String str = it.next();
            if("MYSQL".equals(str)){
                System.out.println("..........");
                list.add("JDBC");
            }
        }

这段代码创建了一个字符串类型的ArrayList,并向其中添加了四个元素。接着,通过iterator()方法获取了该ArrayList的迭代器对象,并使用while循环遍历迭代器。

在循环中,首先使用hasNext()方法检查是否还有下一个元素,然后使用next()方法获取下一个元素。如果当前元素的值等于"MYSQL",则会打印出".........."。接着,在if条件中,代码尝试往列表中添加一个新元素"JDBC"。

然而,由于在迭代器遍历过程中对列表进行了结构性修改(添加元素),根据快速失败机制,会抛出ConcurrentModificationException异常。这是因为在这个案例中,通过迭代器遍历列表,而在遍历过程中修改了列表的结构。

解决该异常我们可以使用for循环,实现元素的添加

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("JavaSE");
        list.add("MYSQL");
        list.add("JavaWeb");
        list.add("JavaEE");

        for (int i = 0; i < list.size(); i++) {
           if ("MYSQL".equals(list.get(i))){
                list.add("JDBC");
           }
        }
        System.out.println(list);

在循环中,首先通过list.get(i)获取索引为i的元素,然后判断是否等于"MYSQL"。如果相等,则在列表末尾添加一个新元素"JDBC"

还可以使用listIterator来解决

java 复制代码
        List<String> list = new ArrayList<>();
        list.add("JavaSE");
        list.add("MYSQL");
        list.add("JavaWeb");
        list.add("JavaEE");
        ListIterator<String> lt = list.listIterator();
        while (lt.hasNext()){
            String str = lt.next();
            if ("MYSQL".equals(str)){
                lt.add("JDBC");
            }
        }
        System.out.println(list);
   

在迭代器的循环中,首先通过lt.next()方法获取下一个元素,然后判断是否等于"MYSQL"。如果相等,则使用lt.add("JDBC")方法在当前元素之前插入一个新元素"JDBC"。

在这种情况下,迭代器的添加操作不会影响迭代的继续进行,并且不会引发ConcurrentModificationException异常。迭代器内部会自动处理这种并发性修改。

最后,打印输出列表的内容。由于使用迭代器进行了元素的插入操作,因此列表中会包含"JDBC"这个新元素。结果会输出修改后的列表内容。

5.LinkedList

LinkedList集合是Java中的一种实现了List接口的链表数据结构。它是由一个个节点组成的,每个节点都包含一个值和指向下一个节点的引用。

与ArrayList不同,LinkedList内部的数据结构是一个双向链表,每个节点既有指向下一个节点的引用,也有指向前一个节点的引用。这使得在LinkedList中插入、删除元素时的操作非常高效,因为只需要修改相邻节点的引用即可,而不需要移动其他元素。

LinkedList集合支持动态的增加或删除元素,因为它不需要连续的内存分配。由于链表的特性,LinkedList对于在列表的开头或结尾插入或删除元素效率较高,但对于通过索引访问元素的效率较低。如果需要频繁地使用索引来访问元素,建议使用ArrayList。

LinkedList还实现了Deque接口,因此它可以被当作双端队列来使用,支持在队列的两端进行插入、删除操作。

总之,LinkedList集合提供了一种灵活的、高效的链表数据结构,适用于需要频繁进行插入、删除操作的场景,但在索引访问方面的性能稍逊于ArrayList。

java 复制代码
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }
}
java 复制代码
public class StuShow {
    public static void main(String[] args) {
        LinkedList<Student> stuList = new LinkedList<>();
        stuList.add(new Student("Jack",19));
        stuList.add(new Student("Kite",14));
        stuList.add(new Student("bill",15));
        stuList.add(new Student("lily",18));

        for (int i = 0; i < stuList.size(); i++) {
            System.out.println("姓名"+stuList.get(i).getName()+"年龄"+stuList.get(i).getAge());
        }

        for (Student stu : stuList) {
            System.out.println("姓名"+stu.getName()+"年龄"+stu.getAge());
        }

        ListIterator<Student> it = stuList.listIterator();
        while(it.hasNext()){
            Student stu = it.next();
            System.out.println("姓名"+stu.getName()+"年龄"+stu.getAge());
        }
    }
}

这段代码是一个示例,展示了如何使用LinkedList集合存储和遍历Student对象。

首先,在main方法中创建了一个LinkedList对象stuList,用于存储Student对象。然后,通过stuList.add方法依次添加了4个Student对象到集合中,每个对象包含姓名和年龄信息。

接下来,通过两种方式进行遍历集合中的元素。第一种方式是使用for循环和索引,通过stuList.size()方法获取集合的大小,使用get方法获取指定索引位置的Student对象,然后通过getName和getAge方法获取对象的姓名和年龄,并打印出来。

第二种方式是使用增强for循环,直接遍历stuList中的每个Student对象,并通过getName和getAge方法获取对象的姓名和年龄,并打印出来。

第三种方式通过ListIterator迭代器来遍历集合中的元素。首先,通过stuList.listIterator()方法获取ListIterator对象,然后使用while循环和it.hasNext()方法判断是否有下一个元素,如果有则通过it.next()方法获取下一个Student对象,再通过getName和getAge方法获取对象的姓名和年龄,并打印出来。

这段代码展示了LinkedList集合的常见用法,包括添加、遍历、获取元素等操作。

相关推荐
腥臭腐朽的日子熠熠生辉20 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian22 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之27 分钟前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen1 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存
绝顶少年2 小时前
Spring Boot 注解:深度解析与应用场景
java·spring boot·后端