List集合详解讲解(特点,常用方法,5种遍历方式,List集合实现类讲解)包含相应练习

4、List集合

(1)List集合的特点和常用方法

List集合继承于Collection接口,List集合本质也是一个接口。

(1)List系列集合特点:
添加的元素是有序(有序指的是存和取的顺序是一样的)、可重复、有索引。
(2)List集合的特有方法

因为List继承于Collection所以List继承了Collection方法,又因为List集合有索引,所以多了很多索引操作的方法。

void add(int index,E element) 在此集合中的指定位置插入指定的元素。

E remove(int index) 删除指定索引处的元素,返回被删除的元素

E set(int index,E element) 修改指定索引处的元素,返回被修改的元素

E get(int index) 返回指定索引处的元素

List集合中删除操作的 注意事项

在调用方法的时候,如果方法出现了重载现象, 优先调用实参跟形参类型一致 的那个方法,//手动装箱,手动把基本数据类型的1,变成Integer类型。

具体请看下面的代码练习:

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ListText1 {
    public static void main(String[] args){
        List<String> list = new ArrayList<>();
        //直接在集合尾部添加元素
        list.add("aaa");
        list.add("ccc");
        list.add("ddd");
        System.out.println(list);
        //指定索引的位置添加元素
        list.add(1,"bbb");
        System.out.println(list);
        //直接删除指定元素
        boolean flag = list.remove("ddd");
        System.out.println(list);
        //删除索引出的元素
        String result1=list.remove(2);
        System.out.println(result1 + list);
        //修改指定索引处的元素
        String result2=list.set(0,"kkk");
        System.out.println(result2 + list);
        //获取指定索引的元素
        String result3=list.get(0);
        System.out.println(result3);
    }
}

List集合中的删除操作:

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ListText2 {
    public static void main(String[] args){
        List<Integer> list = new ArrayList<>();
        
        list.add(1);
        list.add(2);
        list.add(3);
        //问:此时删除的是1这个元素,还是1索引上的元素?
        //答:删除的是索引1上的元素;
        //因为在调用方法的时候,如果方法出现了重载现象,优先调用实参跟形参类型一致的那个方法。
        
        list.remove(1);
        System.out.println(list);
        
        list.add(1,2);
        System.out.println(list);
        
        //手动装箱,手动把基本数据类型的1,变成Integer类型
        Integer i = Integer.valueOf(1);
        list.remove(i);
        
        System.out.println(list);
    }
}

(2)List集合的遍历方式

  • for循环遍历

  • 迭代器遍历

  • 列表迭代器遍历

  • 增强for遍历

  • Lambda表达式遍历

------1、for循环遍历
------2、迭代器遍历

迭代器遍历

迭代器在java中的类是Iterator,迭代器是集合专用的遍历方式。 Iterator是一个接口,Iterator对象也被称为迭代器。迭代器遍历不依赖索引。

Collection集合获取迭代器

方法:Iterator<E> iterator() 返回迭代器对象,默认指向当前集合的0索引

Iterator中常用的方法

boolean hasNext() 判断当前位置是否有元素,有元素返回true,没有元素返回false

E next() 返回当前位置的元素,并将迭代器对象移向下一个位置

void remove() 删除集合里上一次next方法返回的元素。

遍历的语法:

Iterator<String> it = list.iterator() 获取集合对应的迭代器创建指针默认指向0索引

while(it.hasNext()){ 判断是否有元素

String str = it.next(); 获取元素

System.out.println(str);

}

细节:
  1. 如果迭代器已经指向末尾的下一个位置,此时如果再次调用next()方法获取元素,则会报NoSuchElementException 没有这个元素 异常。因为迭代器不依赖索引

  2. 迭代器遍历完毕, 指针不会复位 ,若想重新遍历,则需重新获取一个迭代器对象。

  3. 循环中只能用一次next方法,因为next方法调用一次会移动指针,所以在最后会出现NoSuchElementException异常。

  4. 迭代器遍历时,不能用集合的方法进行增加或者删除( 迭代过程中增加或删除集合元素则运行时会报ConcurrentModificationException 并发异常)

------3、增强for遍历
------4、Lambda表达式遍历

Lambda表达式遍历

利用Lambda表达式里面的方法:

方法:default void forEach(Consumer<? super T> action); 结合Lambda遍历集合

// 方法底层原理: //底层会自己遍历集合,依次获取每个元素,把得到的每个元素,传递给下面的accept方法

下面代码的匿名内部类:new的是大括号中没有名字的类的对象,实现了Consumer<String>()这个接口。

java 复制代码
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class ListText3 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<> ();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        //迭代器遍历
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }
        //增强for遍历
        for(String s: list) {
            System.out.println(s);
        }
        //Lambda表达式遍历
//        list.forEach(new Consumer<String>() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });
        list.forEach( s-> System.out.println(s));
        //普通for循环遍历
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }
}
------5、列表迭代器遍历

ListIterator接口--列表迭代器继承于Iterator接口。

ListIterator创建对象:

ListIterator<E> listIt = 集合.listIterator();

ListInterator常用方法

boolean hasNext()正向: 判断后面有没有元素

E next()正向: 取出下一个元素

boolean hasPrevious()反向: 判断前面有没有元素

E previous()反向: 取出上一个元素

void remove() 删除迭代器遍历到的元素

void add(E e) 在当前位置插入新元素

java 复制代码
import java.util.*;
import java.util.List;
//import java.util.function.Consumer;

public class ListText3 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<> ();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        //列表迭代器
        ListIterator<String> It = list.listIterator();
        while (It.hasNext()) {
            String str = It.next();
            if("bbb".equals(str)){
                list.add("qqq");//这里会运行时异常错误。因为在迭代器遍历中使用集合的方式进行添加
                It.add("qqq");//可以添加,因为使用的是迭代器中的添加方法
            }
        }
        System.out.println(list);
      运行结果:  [aaa, bbb, qqq, ccc]
    }
}

5、List集合的实现类

(1)ArrayList集合类;

因为ArrayList是List的实现类,所以ArrayList也继承了List的方法,这里不再讲解。

List2.addAll(list1);将List1集合添加到list2

ArrayList集合底层原理

(1)利用空参创建的集合,在底层创建一个默认长度为0的数组。

(2)添加第一个元素时,底层 会创建一个新的长度为10的数组。

(3)存满时,会自动扩容1.5倍,即长度为15的数组。而当15的长度也存满时,还会继续扩容1.5倍,持续不断。

(4)如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准。

(2)LinkedList集合

LinkedList集合
  • 底层数据结构是 双链表 ,查询慢,增删快,但是如果操作的是首尾元素,速度也是极快的。

  • LinkedList本身多了很多直接操作首尾元素的特有API。

LinkedList集合特有方法

Public void addFirst(E e) 在该列表开头插入指定的元素

Public void addLast(E e) 将指定元素追加到此列表的末尾

Public E getFirst() 返回此列表的第一个元素

Public E getLast() 返回此列表的最后一个元素

Public E removeFirst() 从此列表中删除并返回第一个元素

Public E removeLast() 从此列表中删除并返回最后一个元素