List接口

List接口概述:

List接口是Collection接口的子类

Collection中的常用子类(List集合、Set集合)。

List接口的用户可以对列表中每个元素的插入位置进行精确地控制。

用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

与 set 不同,列表通常允许重复的元素

List接口的特点:

①它是一个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。

②它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。

③集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。

List接口的常用子类有:

①ArrayList集合

②LinkedList集合

List接口常用方法:

1、增加元素方法

①add(Object e):向集合末尾处,添加指定的元素

②add(int index, Object e):向集合指定索引处,添加指定的元素,原有元素依次后移

2、删除元素删除

①remove(Object e):将指定元素对象,从集合中删除,返回值为被删除的元素

②remove(int index):将指定索引处的元素,从集合中删除,返回值为被删除的元素

3、替换元素方法

set(int index, Object e):将指定索引处的元素,替换成指定的元素,返回值为替换前的元素

4、查询元素方法

get(int index):获取指定索引处的元素,并返回该元素

演示:

public class demo01 {
    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        list.add("You ");
        list.add("are ");
        list.add(2, "beautifal!");
        //前提必须有这个下标
        //list.set(3, "aaa");//下标越界异常
        //删除(返回删除元素)
        String s=list.remove(1);
        System.out.println(s);
        for(String str:list){
            System.out.print(str);
        }
    }
}

Iterator并发修改异常

public class IteratorDemo {
//在list集合迭代元素中,对元素进行判断,一旦条件满足就添加一个新元素
    public static void main(String[] args) {
        //创建List集合
        List<String> list = new ArrayList<String>();
        //给集合中添加元素
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        //迭代集合,当有元素为"abc2"时,集合加入新元素"itcast"
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String str = it.next();
            //判断取出的元素是否是"abc2",是就添加一个新元素
            if("abc2".equals(str)){
                list.remove(0);
            /**
             * 直接运行
             * list.add("itcast");
             * 运行到add的时候出现“并发修改异常”,
             * 导致迭代器并不知道集合中的变化,容易引发数据的不确定性。
             * Exception in thread "main" java.util.ConcurrentModificationException

            */
                if(list.add("itcast")){
                    break;//添加成功以后直接break;不继续判断就可以不出现异常
                }

            }
        }
        //打印容器中的元素
        System.out.println(list);
    }
}

总结:在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。

解决方法:在迭代时,不要使用集合的方法操作元素。

那么想要在迭代时对元素操作咋办?

通过ListIterator迭代器操作元素是可以的,ListIterator的出现,解决了使用Iterator迭代过程中可能会发生的错误情况。

或者像上方那样break。但是不能循环所有元素

public class IteratorDemo2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        ListIterator<String> listit=list.listIterator();
        while(listit.hasNext()){
            if(listit.next().equals("b")){
                /**
                 * ListIterator有add和remove方法,可以向List中添加对象
                 */
                listit.remove();
                listit.add("itcast");
            }
        }
//      Iterator<String> it=list.iterator();
//      while(it.hasNext()){
//          if(it.next().equals("b")){
//              list.remove(0);
//              if(list.add("itcast")){
//                  break;//添加成功以后直接break;不继续判断就可以躲过异常
//              }
//          }
//      }
        System.out.println(list);
    }
}

 一.相同点 

都是迭代器,当需要对集合中元素进行遍历不需要干涉其遍历过程时,这两种迭代器都可以使用。 

二.不同点 

1.使用范围不同,Iterator可以应用于所有的集合,Set、List和Map和这些集合的子类型。而ListIterator只能用于List及其子类型。 

2.ListIterator有add方法,可以向List中添加对象,而Iterator不能。 

3.ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)

历。Iterator不可以。

4.ListIterator可以定位当前索引的位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。 

5.都可实现删除操作,但是ListIterator可以实现对象的修改,set()方法可以实现。Iterator仅能遍历,不能修改。

List集合存储数据的结构

数据存储的常用结构有:堆栈、队列、数组、链表。

1、堆栈,采用该结构的集合,对元素的存取有如下的特点:

  ①先进后出(即,存进去的元素,要在它后面的元素依次取出后,才能取出该元素)。例如,子弹压进弹夹,先压进去的子弹在下面,后压进去的子弹在上 

  面,当枪时,先弹出上面的子弹,然后才能弹出下面的子弹。

  ②栈的入口、出口的都是栈的顶端位置

  ③压栈:就是存元素。即,把元素存储到栈的顶端位置,栈中已有元素依次向栈底方向移动一个位置。

  ④弹栈:就是取元素。即,把栈的顶端位置元素取出,栈中已有元素依次向栈顶方向移动一个位置。

2、队列,采用该结构的集合,对元素的存取有如下的特点:

  ①先进先出(即,存进去的元素,要在后它前面的元素依次取出后,才能取出该元素)。例如,安检。排成一列,每个人依次检查,只有前面的人全部检查完毕后,才能

  排到当前的人进行检查。

  ②队列的入口、出口各占一侧。例如,下图中的左侧为入口,右侧为出口。

3、数组,采用该结构的集合,对元素的存取有如下的特点:

  ①查找元素快:通过索引,可以快速访问指定位置的元素

  ②增删元素慢:

    指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。如下图

    指定索引位置删除元素需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中。

4、链表,采用该结构的集合,对元素的存取有如下的特点:

  ①多个节点之间,通过地址进行连接。例如,多个人手拉手,每个人使用自己的右手拉住下个人的左手,依次类推,这样多个人就连在一起了。

  ②查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素

  ③增删元素快:

    增加元素:操作如左图,只需要修改连接下个元素的地址即可。

    删除元素:操作如右图,只需要修改连接下个元素的地址即可。

ArrayList集合

ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

LinkedList集合

LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。

LinkedList<String> link = new LinkedList<String>();
  //添加元素
   link.addFirst("abc1");
   link.addFirst("abc2");
   link.addFirst("abc3");
   //获取元素
   System.out.println(link.getFirst());
   System.out.println(link.getLast());
   //删除元素
   System.out.println(link.removeFirst());
   System.out.println(link.removeLast());
        
   while(!link.isEmpty()){ //判断集合是否为空
       System.out.println(link.pop()); //弹出集合中的栈顶元素
   }
原文地址:https://www.cnblogs.com/Ace-suiyuan008/p/9419160.html