面试高频知识点整理——集合篇(包含底层源码)

本文阅读 10 分钟
首页 代码,Java 正文

集合的概念

        关于集合,首先我们得知道什么是集合,集合的概念是什么,这是最基础的,也是最基本的,那后面面试官问什么,才有可能一一答来。那什么是集合呢?

  1. 集合类存放在java.util包中
  2. 集合类主要有3种:set(集)、list(列表)、map(映射)
  3. 集合存放的都是对象的引用,而非对象的本身。所以我们称集合中的对象就是对象的引用。

        简单的说:集合就是一个放数据对象引用的容器,不能放基本数据类型,只能放对象。而数据可以放基本数据类型。

集合的简要结构图

img

集合的应用场景

img         从以上就可以看到,如果前端有一个按钮需要查询所有学生信息,那具体的逻辑代码的实现就需要后端实现,后端需要访问数据库,数据库会查询出所有学生信息,然后再返回给后端接口,后端接口再把每一条数据返给前端,过于麻烦,浪费时间,我们就可以把这些数据放到一个集合里,然后只需要把这个集合返回给前端,让前端遍历就行了。

Collection接口

collection常用方法

public class demo { 
    public static void main(String[] args) { 
        /** * 集合collection常用的方法: * 增加:add(E e)、addAll(Collection<? extends E> c) * 删除:clear() 、remove(Object o) * 修改: * 判断:contains(Object o)、equals(Object o)、isEmpty() * 查看:iterator()、size() */
        //add(E e):向集合中添加一个元素
        //创建一个集合对象,接口不能创建对象,只能利用实现类创建对象
        Collection collection = new ArrayList();
        //集合有一个特点,只能存放引用数据类型的数据,不能是基本数据类型的数据。
        //基本数据类型会自动装箱,对应包装类。 int————integer
        collection.add(13);
        collection.add(14);
        System.out.println("========add======"+collection);

        //addAll(Collection<? extends E> c),将另外一个集合也添加到此集合中
        //新建一个集合,采用把数组转为为集合的方式
        List<Integer> lists = Arrays.asList(new Integer[]{ 1, 4, 6});
        collection.addAll(lists);
        System.out.println("=====addAll===="+collection);
        //clear():清空集合中的数据
        collection.clear();
        //isEmpty():判断集合是否为空
        System.out.println("=========isEmpty======"+collection.isEmpty());
        //size():查询集合中数据的个数
        System.out.println("==========size()========"+collection.size());


    }
}

        运行结果如下: img

collection集合的遍历方式

public class demo2 { 
    public static void main(String[] args) { 
        Collection collection = new ArrayList();
        collection.add(13);
        collection.add(14);
        collection.add("mengmeng");
        //方式一:增强for循环
        for(Object o:collection){ 
            System.out.print(o+"\t");
        }
        System.out.println();
        System.out.println("------------------------");
        //方式二:iterator()
        Iterator iterator = collection.iterator();
        while (iterator.hasNext()){ 
            System.out.print(iterator.next()+"\t");
        }
    }
}

        我们需要说一下iterator()它的原理,iterator也叫做迭代器。前面我们说过collection底层是数组的数据结构,现在我们通过iterator迭代器遍历集合,先从头的部分,也就是下标为0的位置开始遍历,iterator里面有一个方法hasNext,通过这个方法来判断有没有下一个元素,如果有返回true,没有的话就返回false。若是返回true,说明有元素,就可以把当前元素输出在控制台,也就是通过next方法,并移动到下一个下标的位置重新进行判断,以此类推。直到移动到最后一个位置时,即hasNext返回false时,此时才是遍历完毕。

List接口

List接口常用的方法

public class demo3 { 
    public static void main(String[] args) { 
        /** * 集合List常用的方法: * 增加:add(int index, E element) * 删除:remove(int index) 、remove(Object o)从collection中继承过来的 * 修改:set(int index, E element) * 判断: * 查看:get(int index) */
        List list = new ArrayList<>();
        list.add(1);
        list.add(4);
        list.add(6);
        list.add(2);
        list.add("abc");
        System.out.println("原来集合的数据:"+list);
        //add(int index, E element):在指定的位置插入一个数据
        list.add(2,"mengmeng");
        System.out.println("插入数据之后集合的数据:"+list);
        //set(int index, E element):修改指定位置的数据
        list.set(3,8);
        System.out.println("修改之后的集合数据:"+list);
        //remove(int index):当集合中存放的是Integer数据类型时,调用这个移除方法
        list.remove(2);
        System.out.println("移除数据之后集合的数据:"+list);
        //remove(Object o)
        list.remove("abc");
        System.out.println("移除数据之后集合中的数据:"+list);
        //List的遍历
        //方式一:for循环
        System.out.println("遍历list集合的方式一:");
        for (int i=0;i<list.size();i++){ 
            System.out.print(list.get(i)+"\t");
        }
        //方式二:增强for循环
        System.out.println();
        System.out.println("遍历list集合的方式二:");
        for (Object obj:list) { 
            System.out.print(obj+"\t");
        }
        //方式三:迭代器iterator
        System.out.println();
        System.out.println("遍历list集合的方式三");
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){ 
            System.out.print(iterator.next()+"\t");
        }

    }
}

ArrayList实现类

JDK1.7时的源码

        1,我们首先先把idea中的jdk版本切换到1.7,切换方式如下: img         2,ArrayList实现接口有失误,即父类AbstractList已经实现了接口List,而ArrayList又实现了一次。集合的创始人也承认了这个问题,但是后期jdk更新时,也没有做修改,觉得没毕业。

img         3,底层有两个重要的属性:elementData和size,即ArrayList底层是数组的重要原因。 img

        4,在jdk1.7时,调用构造器时,会给底层数据elementData初始化数据为10。 img         5,往arrayList数组里添加数据时,调用底层的代码,如下:

img

        6,当底层数组初始化的10个位置都满的时候就开始进行数组的扩容了,扩容长度为原数组的1.5倍。

img img img <font size="3" color="red">        小总结:jdk1.7时,ArrayList特点:         1,底层是数组的数据结构。         2,在调用构造器的时候,数组初始化长度为10。         3,扩容的时候,扩展为原数组的1.5倍。</font>

JDK1.8时的源码

        1,底层依旧是Object类型的数组,源码中仍旧有两个重要的参数:elementData和size。 img         2,使用代码ArrayList arrayList = new ArrayList();调用无参的构造器的时候,底层初始化的是一个长度为0空的数组,不再是直接赋值10。

img <font size="3">        3,调用add方法时,才完成了对底层数组初始化赋值的一个过程,赋值为10。 </font>

img img img img <font size="3" color="red">        小总结:jdk1.8时,ArrayList特点:         1,底层依旧是一个数组类型的数据结构,但是是一个空的数组。         2,调用add方法之后才重新为数组赋值,新数组的长度为10,节省了内存。</font>

        区别:1.7在调用构造器的时候就给底层数组初始化为10,不使用数组的时候也会初始化,会造成资源浪费。1.8时是在add方法时才初始化为10。

Vector实现类

底层源码

        1,底层依旧是一个数组的数据结构,用elementData表示数组中的实际有效长度

img         2, Vector vector = new Vector();调用构造器的时候为底层数组初始化长度为10。 img         3,add()方法添加数据时,达到底层数组长度的最大值时,底层数组开始扩容,扩展为原数组长度的2倍,这是与ArrayList的区别。 img         4,是线程安全的。 img

Vector与ArrayList的区别

        1,ArrayList底层扩容是原来的1.5倍,Vector是原来的2倍。         2,ArrayList不是线程安全的,但效率高,Vector是线程安全的,但效率低。

Vector与ArrayList的优点

        由于两者底层都是数组的数据结构,所以它们的优缺点与数组也类似:         1,查询的效率高,但是插入、删除时效率低。         2,数据内容可以重复。

LinkedList集合

LinkedList常用的方法

public class Demo5 { 
    /** * LinkedList集合常用的方法: * 增加:addFirst(E e) 、addLast(E e) * offer(E e) 、offerFirst(E e)、offerLast(E e) * 删除:poll()、pollFirst()、pollLast() * removeFirst()、removeLast() * 修改: * 查看:element()、getFirst()、getLast() * indexOf(Object o)、lastIndexOf(Object o) * peek()、E peekFirst() 、peekLast() * 判断: */
    public static void main(String[] args) { 
        //创建一个LinkedList集合,因为底层代码是一个泛型,所以我们一般创建对象时也是创建一个泛型集合
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("q");
        linkedList.add("qw");
        linkedList.add("qw");//可以添加重复数据
        //addFirst(E e) 、addLast(E e) 向首部、尾部插入数据
        linkedList.addFirst("a");
        linkedList.addLast("z");
        System.out.println("============"+linkedList);
        //offer(E e) 、offerFirst(E e)、offerLast(E e) 分别在尾部、首部、尾部添加数据
        linkedList.offer("x");
        linkedList.offerFirst("b");
        linkedList.offerLast("y");
        System.out.println("============"+linkedList);
        //poll()、pollFirst()、pollLast() 分别是删除首部、首部、尾部的数据
        System.out.println("=============poll()删除的元素是:"+linkedList.poll());
        System.out.println("=============pollFirst()删除的元素是:"+linkedList.pollFirst());
        System.out.println("=============pollLast()删除的元素是:"+linkedList.pollLast());
        System.out.println("=============removeFirst()删除:"+linkedList.removeFirst());
    }
}

        问题:pollFirst()和removeFirst()都是表示删除的,为什么要存在两组呢?它们有什么区别吗?

        回答:当数组为空的时候,用pollFirst()可以删除null,代码不会报错,用removeFirst()删除的时候,代码会报错。pollFirst()是jdk1.6以后提出的,提高了代码的健壮性。

LinkedList底层源码

        首先我们先大致简要的说一下Linkedlist的底层数据结构。下面这个图是梦梦在网上看视频的时候截的一张图,感觉还挺不错的,就拿来用了。 img         总结:Linkedlist的底层是一个双向链表的结构,双向的意思是:能够前后分别指向对象的链表地址,所以LinkedList底层是靠一个一个简要的对象连接起来。

        未完,后续在路上。。。。

        

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_46540738/article/details/117597214
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复