25-集合--List和Set比较+List+ListIterator+List取出元素的三种方式+List特有的内容

一、List和Set比较

1、List

(1)有序(存入和取出的顺序一致)

(2)元素都有索引(角标)

(3)元素可以重复

2、Set

(1)无序(有可能会有序,但几率不高)

(2)元素不能重复

List和Set最严重的区别在于:是否有重复元素

二、List

1、有序的collection。此接口的用户可以对列表中每个元素的插入位置进行精确的控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素

2、List特有的常见方法,都有一个共性特点:都可以操作角标 -- List最大的特点。即 凡是可以操作角标的,都是List的特有方法

3、只有List集合可以实现对元素的增删改查(Collection不具备修改功能)

4、方法(凡是参数为角标的方法,返回值多为对象E)

(1)迭代器

        Iterator<E> iterator():返回按适当顺序在列表的元素上进行迭代的迭代器

        ListIterator<E> listIterator():返回此列表元素的列表迭代器(按适当顺序)

        ListIterator<E> listIterator(int index):返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。指定的索引表示next()的初始调用所返回的第一个元素

(2)添加

        void add(int index, E element):在列表的指定位置插入指定元素

        boolean addAll(int index, Collection<? extends E> c):将指定集合c中的所有元素都插入到列表中的指定位置

        boolean add(E e):向列表的尾部添加指定的元素

        boolean addAll(Collection<? extends E> c):将指定集合c中的所有元素添加到此列表的结尾

        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");
        System.out.println(list);   //[abc1, abc2]
        //新插入的元素在角标1的位置上
        list.add(1, "abc3");
        System.out.println(list);   //[abc1, abc3, abc2]

(3)删除

        E remove(int index):移除列表中指定位置的元素,返回被移除的元素

        boolean remove(Object o):从此列表中移除第一次出现的指定元素(如果存在)

        boolean removeAll(Collection<?> c):移除collection中也包含在指定集合c中的所有元素

        void clear():从列表中移除所有元素。此调用返回后该列表将是空的

注:参数为对象的删除方法,不返回对象,因为删除的对象是指定好的(已知)。参数为角标的删除方法,会返回被删除的对象,因为指定角标对应的是哪个对象并不知道

(4)修改

        E set(int index, E element):用指定元素替换列表中指定位置的元素,返回被替换的元素 -- 只有List有修改功能

(5)获取

        E get(int index):返回列表中指定位置的元素

        int indexOf(Object o):返回此列表中第一次出现的指定元素的索引

        int lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引

        List<E> subList(int fromIndex, int toIndex):返回列表中指定的fromIndex和toIndex之间的部分视图(包含fromIndex,不包含toIndex)。eg:从列表中移除了元素的范围:list.subList(from, to).clear();    具体说明见第5点

        int size():返回列表中的元素数

(6)判断

        boolean contains(Object o):如果列表包含指定的元素,则返回true

        boolean containsAll(Collection<?> c):如果列表包含指定集合c的所有元素,则返回true

        boolean isEmpty():如果列表不包含元素(列表为空),则返回true

(7)其他

        boolean retainAll(Collection<?> c):仅在列表中保留指定集合c中也包含的元素(取交集)

        Object[] toArray():返回按适当顺序包含列表中的所有元素的数组

5、List<E> subList(int fromIndex, int toIndex); 方法说明

(1)该方法返回的是父list的一个视图,从fromIndex(包含),到toIndex(不包含)。fromIndex = toIndex 表示子list为空

(2)对于非结构性修改,父子list做的非结构性修改都会影响到彼此

(3)对于结构性修改,子list的所有操作都会反映到父list上,但父list的修改将会导致返回的子list失效

注:非结构性修改:不涉及到list的大小改变的修改

        List list = new ArrayList();
        list.add("a");

        //使用构造器创建一个包含list的列表list1
        List list1 = new ArrayList(list);
        //使用subList生成与list相同的列表list2
        List list2 = list.subList(0, list.size());

        //结构性修改(长度改变):子list的修改会影响到父list
        list2.add("b");

        System.out.println(list.equals(list1)); //false
        System.out.println(list.equals(list2)); //true
        List c = new ArrayList();
        c.add("abc1");
        c.add("abc2");
        c.add("abc3");
        c.add("abc4");
        System.out.println(c);  //[abc1, abc2, abc3, abc4]

        List a = c.subList(1,3);
        System.out.println(a);  //[abc2, abc3]
        System.out.println(c);  //[abc1, abc2, abc3, abc4]

        //结构性修改(长度改变):子list的修改会影响到父list
        a.clear();
        System.out.println(a);  //[]
        System.out.println(c);  //[abc1, abc4]

        //结构性修改(长度改变)):父list的修改会导致子list失效
        c.add("text");
        System.out.println(c);  //[abc1, abc4, text]
//        System.out.println(a);  //报错,java.util.ConcurrentModificationException
        List parentList = new ArrayList();
        for (int i = 0; i < 5; i++) {
            parentList.add(String.valueOf(i));  //parentList:[0, 1, 2, 3, 4]
        }
        List subList = parentList.subList(1, 3);    //subList:[1, 2]
        
        //子修改
        //非结构性修改(长度不变):子list和父list相互影响
        subList.set(0, "new 1");    //subList:[new 1, 2], parentList:[0, new 1, 2, 3, 4]
        //结构性修改(长度改变):子list的修改会影响到父list
        subList.add(String.valueOf(2.5));   //subList:[new 1, 2, 2.5], parentList:[0, new 1, 2, 2.5, 3, 4]

        //父修改
        //非结构性修改(长度不变):父list和子list相互影响
        parentList.set(2, "new 2");     //parentList:[0, new 1, new 2, 2.5, 3, 4], subList:[new 1, new 2, 2.5]
        //结构性修改(长度改变):父list修改导致子list失效
        parentList.add("undefine"); //parentList:[0, new 1, new 2, 2.5, 3, 4, undefine], subList:报错,java.util.ConcurrentModificationException

三、ListIterator

1、interface ListIterator<E> extends Iterator<E>:可以按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置

2、ListIterator是List特有的迭代器(列表迭代器)

3、方法

(1)void add(E e):将指定的元素插入列表。该元素直接插入到next()返回的下一个元素的前面,或者previous()返回的下一个元素之后

(2)boolean hasNext():以正向遍历列表时,如果列表迭代器有多个元素,则返回true

(3)boolean hasPrevious():如果以逆向遍历列表,列表迭代器有多个元素,则返回true

(4)E next():返回列表中的下一个元素。可以重复调用此方法来迭代此列表

(5)int nextIndex():返回对next()的后续调用所返回元素的索引

(6)E previous():返回列表中的前一个元素。可以重复调用此方法来迭代列表

(7)int previousIndex():返回对previous()的后续调用所返回元素的索引

(8)void remove():从列表中移除由next()或previous()返回的最后一个元素。对于每个next()或previous()调用,只能执行一次此调用

(9)void set(E e):用指定元素替换next()或previous()返回的最后一个元素

注:正向遍历的指针是从第一个元素的左边开始,到最后一个元素结束;逆向遍历的指针是从最后一个元素的右边开始,到第一个元素结束

4、只有列表迭代器ListIterator可在迭代过程中对元素进行增删改查操作

        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");

        Iterator it = list.iterator();
        while (it.hasNext()) {
            //用Object类型接收是因为:public boolean add(Object obj);,添加的是Object类型的元素(向上转型),向外取出时也要用Object接收
            Object obj = it.next(); //java.util.ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出异常
            if (obj.equals("abc2")) {
                //引发异常的语句。迭代器拿到集合中元素的个数为2个,而集合add的新元素,迭代器并不知道。即 集合和迭代器同时对元素进行修改,就会导致迭代出问题
                list.add("abc3");
            }
        }
        /**
         * 思考:
         *
         * 问题:迭代器和集合同时访问造成并发,抛出异常
         * 如何避免问题:使用集合操作时不迭代,使用迭代操作时不集合操作,不冲突即可
         * 解决:在迭代过程中不用集合操作(list.add()),就只能用迭代操作(迭代进行集合中元素的增删改查)
         *
         * 迭代器操作
         * 问题:Iterator只有 hasNext()、next()、remove()三个方法,没有添加和修改
         * 解决:可以使用Iterator的子接口:ListIterator(列表迭代器)
         * ListIterator的好处:可以在迭代过程中对元素进行增删改查
         */
        List list = new ArrayList();
        list.add("abc1");
        list.add("abc2");

        //列表迭代器ListIterator,此迭代器只有List有 (只有ListIterator可以实现在迭代过程中对元素的增删改查)
        ListIterator it = list.listIterator();
        while (it.hasNext()) {
            //用Object类型接收是因为:public boolean add(Object obj);,添加的是Object类型的元素(向上转型),向外取出时也要用Object接收
            Object obj = it.next();
            if (obj.equals("abc2")) {
                //调用迭代器的方法进行增删改查,而不是集合的
                //下面语句一次只能打开一个
//                it.add("abc3"); //[abc1, abc2, abc3]。加在“abc2”后面
//                it.set("abc4"); //[abc1, abc4]。将“abc2”换成“abc4”
            }
        }
        System.out.println(list);

四、List取出元素的方式(三种)

1、iterator():迭代器。通用,Collection的子类都具备

2、listIterator():迭代器。List特有

3、get(int index):根据角标获取元素。List特有

        List list = new ArrayList();
        list.add("abc");

        /**
         * List有三种取出元素的方式,后两种是List特有的
         */
        /**
         * 方法一:iterator(),通用 -- Collection的子类都具备
         */
//        Iterator it = list.iterator();
//        while (it.hasNext()){
//            it.next();
//        }

        /**
         * 方法二:listIterator(),List特有
         */
        ListIterator it = list.listIterator();
        while (it.hasNext()) {
            it.next();
        }

        /**
         * 方法三:get(),List特有
         */
        for (int i = 0; i < list.size(); i++) {
            list.get(i);
        }

五、List特有的内容(只有List有)

(1)可以操作角标

(2)可以实现对元素的增删改查

(3)有列表迭代器ListIterator,可以在迭代过程中对元素进行增删改查

猜你喜欢

转载自blog.csdn.net/ruyu00/article/details/81943035