Collection

是单列集合的祖宗接口,所有单列集合都可继承。有如下方法:add(),clear(),remove(),contain(),isEmpty(),size().

collection是一个接口,因此不能直接创建他的对象,需要创建实现其实现类的对象。

Collection中方法

往list集合中添加数据,add()方法永远返回true(因为数据可以重复)。而对于set集合,添加原先不存在的数据会提示true,而对于原先已存在的数据会提示false(set集合不可重复)。

对于remove()方法,只能通过对象删除,不能通过索引删除。删除成功提示true,失败为false;

对于contains()方法,判断是否包含,返回的是布尔值。当集合中存储的是自定义对象时(即Collection<(此处为自定义对象时)> coll = new ArrayList();),若也想通过contains方法来判断元素是否存在,则需在对应的自定义对象的javabean中重写equals()方法(为什么:因为contains()方法底层调用了equals()方法进行判断,若在自定义对象中不重写,则会自动调用父类Object的equals()方法,而Object中进行比较是利用地址值进行比较的,因此会出现错误)

对于inEmpty()方法,判断集合长度是否为空

size()方法,获得集合长度

import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<>();
        
        
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        System.out.println(coll);


//        coll.clear();
//        System.out.println(coll)

        coll.remove("aaa");
        System.out.println(coll);

        boolean a = coll.contains("aaa");
        System.out.println(a);
        
        
    }
}

Collection中遍历

1.迭代器遍历

迭代器(Iterator)遍历不依赖索引。

迭代器通过判断下一个有无元素,并且不断移动指针实现遍历。

正因为迭代器中有romove()的删除方法,因此当遍历过程中需要删除元素时可使用,若仅需要遍历则可使用增强for或lambda表达式。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo2 {
    public static void main(String[] args) {

        Collection<String> coll = new ArrayList<>();
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        coll.add("ddd");

        //用集合对象获取迭代器对象
        //此时迭代器默认指向0索引
        Iterator<String> iterator = coll.iterator();

        while(iterator.hasNext()){

            String str = iterator.next();
            System.out.println(str);

        }

    }
}

注意:1.迭代器遍历完毕,指针不会复位(不会自动回到开头)。2.想再次遍历,只能再获取一个迭代器对象。3.循环中只能一次next,迭代器遍历不能用集合方式进行增删(迭代器有自带的删除方法remove(),)。4.当迭代器指针指向最后没有元素位置时,会报NosuchElementException异常,而非数组越界类似的异常。

2.增强for遍历

底层就是迭代器,简化了迭代器的书写。

单列集合和数组才可以用增强for进行遍历。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo2 {
    public static void main(String[] args) {

        Collection<String> coll = new ArrayList<>();
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        coll.add("ddd");


        //迭代器遍历
        //用集合对象获取迭代器对象
        //此时迭代器默认指向0索引
//        Iterator<String> iterator = coll.iterator();
//
//        while(iterator.hasNext()){
//
//            String str = iterator.next();
//            System.out.println(str);
//
//        }

        //增强for遍历
        //c是第三方变量,依次表示集合中各个元素
        //coll.for
        //以上输入方式可以快速生成增强for循环
        for (String c : coll){
            System.out.println(c);
        }

        //


    }
}

3.lambda表达式遍历

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;

public class CollectionDemo2 {
    public static void main(String[] args) {

        Collection<String> coll = new ArrayList<>();
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        coll.add("ddd");


        //迭代器遍历
        //用集合对象获取迭代器对象
        //此时迭代器默认指向0索引
//        Iterator<String> iterator = coll.iterator();
//
//        while(iterator.hasNext()){
//
//            String str = iterator.next();
//            System.out.println(str);
//
//        }

        //增强for遍历
        //c是第三方变量,依次表示集合中各个元素
        //coll.for
        //以上输入方式可以快速生成增强for循环
//        for (String c : coll){
//            System.out.println(c);
//        }

        //匿名内部类-->lambda表达式
        //forEach方法底层是使用for循环遍历集合,把得到的元素传递给accept方法中的s。
        coll.forEach(new Consumer<String>() {
            @Override
            //s依次表示集合中每个数据
            public void accept(String s) {
                System.out.println(s);
            }
        });
        
        //lambda表示式
        coll.forEach(s-> System.out.println());

    }
}

List

collection的方法list都继承了,list因为有索引有额外的关于索引的操作。

List方法

add(),remove(),set(),get()。(这些方法都是可以根据索引直接操作的方法)

import java.util.ArrayList;
import java.util.List;

public class ListDemo {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

        System.out.println(list);

        //add方法,添加元素,后面元素依次后移
        list.add(1,"nnn");

        System.out.println(list);

        //remove删除指定索引元素,后面元素依次前移
        //方法出现重载,会默认调用实参和形参类型相同的方法。
        //当集合中数据为数字时,想直接根据数值删除,需要进行手动装箱操作
        //Integer i = Integer.valueOf(1);
        list.remove(2);
        System.out.println(list);

        //set
        list.set(1,"666");
        System.out.println(list);

    }
}

List集合的遍历方式

1.迭代器

与collection类似

2.列表迭代器(特殊)

这是list集合特殊的迭代器,也就因为是list集合,所以其存在索引,因此,它存在在迭代器过程中进行增加的功能,这也就是与普通迭代器不同的地方。listIterator也有特殊的循环方法存在从前往后,与从后往前两种(但是从后往前具有一定局限性,需要先让迭代器的指针走到最后,再从后往前走)

3.增强for

与collection类似

4.lambda表达式遍历

与collection类似

5.普通for(根据索引)

与collection类似

总代码:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;

public class ListDemo2 {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");

        Iterator<String> iterator = list.iterator();

        //迭代器
        while (iterator.hasNext()){
            String s = iterator.next();
            System.out.println(s);
        }
        System.out.println("--------------");
        //增强for
        for (String s : list) {
            System.out.println(s);
        }

        System.out.println("--------------");
        //lambda表达式
        list.forEach(s->System.out.println(s));

        System.out.println("--------------");
        //普通for
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }

        System.out.println("--------------");
        //列表迭代器
        //列表迭代器可以在迭代器的遍历过程中进行增加删除(这是与普通迭代器不同的地方)
        //这一部分与原来的迭代器是一摸一样的。
        ListIterator<String> it = list.listIterator();
        while (it.hasNext()){
            String next = it.next();
            if("bbb".equals(next)) {
                it.add("这是用list迭代器的方法进行数据添加");
            }
        }
        System.out.println(list);

    }
}

总结:在遍历过程中需要删除元素,使用迭代器。

           在遍历过程中需要增加元素,使用列表迭代器。

           仅仅想要实现遍历,使用增强for或lambda表达式。

           如果遍历过程中想要对索引进行操作,可用普通for循环。

ArrayList

他的父类有Collection和List。继承了他们的方法。

ArrayList的底层原理

ArrayList的底层是数组结构的。

利用空参构造创建ArrayList集合(叫做ElementData),会在底层创建一个默认长度为0的数组。

添加第一个元素会创建一个的长度为10(此处10,是java中默认的数组初始值,DEFAULT_CAPACITY)的数组。用size指向0索引。(size即表示元素个数,又表示下一个元素应该存入的位置)

当元素存满时数组扩容有两种情况1.数组会扩容1.5倍,也就是新建一个大1.5倍的数组,将原数组拷贝进去。2.当一次添加的数组极大,远远超过扩容1.5倍的大小,因此此时创建的新数组长度就以实际长度为准。

LinkList

LinkList的底层原理

LinkList的底层是双向链表,查询慢,增删快。LinkList也有很多独有的API,用于头尾元素的处理:

addFirst(),addLast(),getFirst(),getLast(),removeFirst(),removeLast()。(这些方法的效果用其父类list的方法也可以解决,因此这些方法使用不多。)

一个Node由三个成员变量组成(item,next,prev),存储当前数据,下一个数据节点,上一个数据节点。

主要是使用LinkLast方法实现链表的形成。

Interator的底层原理

调用iterator方法实际上就是创建了一个迭代器对象,会初始化三个成员变量。创建一个指针cursor(默认指针指向0索引)。LastRet = -1 会指向刚刚指向的索引。modCount指代集合变化的次数,用来记录迭代器中对数据进行操作的次数,如果在这用集合的方式修改了数据,就会像上面提到的迭代器不能用集合方法进行数值修改,报出并发修改异常。

hasNext(),方法中使用cursor != size 进行判断,输出布尔值。(就是用光标的索引和数组的长度进行比较。)

next()方法最终return了一个elementData,也就是返回了索引所指的元素值,并将索引后移一位。

问:如何避免并发修改异常

答:避免在使用迭代器或增强for遍历数组过程中使用集合的方法增加或删除元素,深层原因如上modCount。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐