List系列集合-CSDN博客

118 阅读6分钟

目录

一. List集合特点、特有API

 List的实现类的底层原理

二. List集合的遍历方式小结

List集合的遍历方式有几种?

三. ArrayList集合的底层原理

 四. LinkedList集合的底层原

一. List集合特点、特有API

 

 List的实现类的底层原理

  • ArrayList底层是基于数组实现的:根据索引定位元素快,增删相对慢。
  • LinkedList底层基于双链表实现的:查询元素慢,增删首尾元素是非常快的。

public class ListDemo01 {
    public static void main(String[] args) {
        // 1.创建一个ArrayList集合对象:
        // List:有序,可重复,有索引的。
        List<String> list = new ArrayList<>(); // 一行经典代码!多态
        list.add("Java");
        list.add("Java");
        list.add("HTML");
        list.add("HTML");
        list.add("MySQL");
        list.add("MySQL");

        // 2.在某个索引位置插入元素。
        list.add(2, "黑马");
        System.out.println(list); // [Java, Java, 黑马, HTML, HTML, MySQL, MySQL]

        // 3.根据索引删除元素,返回被删除元素
        System.out.println(list.remove(1)); // Java
        System.out.println(list); // [Java, 黑马, HTML, HTML, MySQL, MySQL]

        // 4.根据索引获取元素:public E get(int index):返回集合中指定位置的元素。
        System.out.println(list.get(1)); // 黑马

        // 5.修改索引位置处的元素: public E set(int index, E element)
        System.out.println(list.set(1, "传智教育")); // 黑马
        System.out.println(list); // [Java, 传智教育, HTML, HTML, MySQL, MySQL]
    }
}

二. List集合的遍历方式小结

List集合的遍历方式有几种?

  1. 迭代器
  2. foreach / 增强for循环
  3. Lambda表达式
  4. for循环(因为List集合存在索引)
package com.gch.d5_collection_list;

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

/**
    拓展:List系列集合的遍历方式有:4种。

    List系列集合多了索引,所以多了一种按照索引遍历集合的for循环。

    List遍历方式:
        (1)for循环。(独有的,因为List有索引)。
        (2)迭代器。
        (3)foreach。
        (4)JDK 1.8新技术。
 */
public class ListDemo02 {
    public static void main(String[] args) {
        List<String> lists = new ArrayList<>(); // 多态
        lists.add("java1");
        lists.add("java2");
        lists.add("java3");

        /** (1)for循环。 */
        System.out.println("----------for循环-------------");

        for (int i = 0; i < lists.size(); i++) {
            String ele = lists.get(i);
            System.out.println(ele);
        }


        /** (2)迭代器。 */
        System.out.println("----------迭代器-------------");
        Iterator<String> it = lists.iterator();
        while (it.hasNext()){
            String ele = it.next();
            System.out.println(ele);
        }

        /** (3)foreach */
        System.out.println("---------foreach--------------");
        for (String ele : lists) {
            System.out.println(ele);
        }

        /** (4)JDK 1.8开始之后的Lambda表达式  */
        System.out.println("-----------Lambda表达式------------");
        lists.forEach(s -> {
            System.out.println(s);
        });

    }
}

三. ArrayList集合的底层原理

  1. ArrayList是一种基于数组实现的动态数组,它实现了List接口,可以动态的增加、删除和修改元素。
  2. 利用空参创建的ArrayList集合,在底层创建一个默认长度为0的数组,数组名叫elementData,size等于0。
  3. 添加第一个元素时,底层会创建一个新的长度为10的数组,在数组当中,默认初始值都是null。
  4. 存满时,会扩容1.5倍,当数组存满时,它会创建一个新的数组,新数组的长度是原来的1.5倍,也就是长度为15,索引为0-14的一个数组,然后再使用Arrays工具类的copyOf()方法把所有的元素全部拷贝到新数组当中。
  5. 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准。
  6. elementData是ArrayList底层数组的名称。
  7. ArrayList底层就是数组,而且数组有个名字,叫elementData,与此同时,Java它在底层还有一个成员变量叫size,size用来记录元素的个数,也就是集合的长度,它同时也表示了下一个元素的应存入的位置。
  8. ArrayList根据索引定位元素快,增删相对慢,因为它底层是数组,在插入和删除元素时,需要移动其他元素,因此效率较低,但都是理论上,因为现在的计算机性能都比较强大。

 四. LinkedList集合的底层原理

  • LinkedList时一种基于链表实现的数据结构,它可以动态添加和删除元素。
  • LinkedList底层使用双向链表存储元素,每个节点包含一个元素和指向前一个节点和后一个节点的指针 / 引用。
  • 因为链表的长度是可变的,所以在添加或删除元素时,只需要修改相应节点的引用即可,不需要像数组一样移动其他元素。
  • 当添加元素时,创建一个新的节点,并将其插入到链表的末尾。
  • 当删除元素时,找到要删除的节点,并将其前一个节点的指针指向其后一个节点,将其后一个节点的指针指向前一个节点。
  • LinkedList支持快速插入和删除操作,但是在随机访问 / 查询元素时,需要遍历整个链表,因此效率较低。
  • LinkedList适用于需要频繁添加和删除元素的场景,如LRU缓存和高新能队列。
  • LinkedList增删首尾元素是非常快的!

LInkedList可以完成队列结构和栈结构(双链表),双链表是队列结构和栈结构的结合体。

package com.gch.d5_collection_list;

import java.util.LinkedList;
import java.util.List;

/**
     目标:LinkedList集合。

     Collection集合的体系:
                Collection<E>(接口)
     /                                       \
     Set<E>(接口)                             List<E>(接口)
     /                                   /                    \               \
     HashSet<E>(实现类)                   LinkedList<E>(实现类) Vector(实现类)  ArrayList<E>(实现类)
     /
     LinkedHashSet<E>(实现类)

     Collection集合体系的特点:
         Set系列集合: 添加的元素,是无序,不重复,无索引的。
             -- HashSet:添加的元素,是无序,不重复,无索引的。
             -- LinkedHashSet:添加的元素,是有序,不重复,无索引的。
         List系列集合:添加的元素,是有序,可重复,有索引的。
             -- LinkedList: 添加的元素,是有序,可重复,有索引的。
             -- Vector: 添加的元素,是有序,可重复,有索引的。线程安全(淘汰了)
             -- ArrayList: 添加的元素,是有序,可重复,有索引的。

     LinkedList也是List的实现类:底层是基于双链表的,增删比较快,查询慢!!
     LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的
     所以LinkedList除了拥有List集合的全部功能还多了很多操作首尾元素的特殊功能:
         - public void addFirst(E e):将指定元素插入此列表的开头。
         - public void addLast(E e):将指定元素添加到此列表的结尾。
         - public E getFirst():返回此列表的第一个元素。
         - public E getLast():返回此列表的最后一个元素。
         - public E removeFirst():移除并返回此列表的第一个元素。
         - public E removeLast():移除并返回此列表的最后一个元素。
         - public E pop():从此列表所表示的堆栈处弹出一个元素。
         - public void push(E e):将元素推入此列表所表示的堆栈。

    小结:
         LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的。
         所以提供了很多操作首尾元素的特殊API可的实以做栈和队列现。

         如果查询多而增删少用ArrayList集合。(用的最多的)
         如果查询少而增删首尾较多用LinkedList集合。
 */
public class ListDemo03 {
    public static void main(String[] args) {
        // LinkedList可以完成队列结构,和栈结构 (双链表)
        // 双链表是栈和队列的结合体
        // 1、做一个队列: queue:队列
        LinkedList<String> queue = new LinkedList<>();
        // 入队
        queue.addLast("1号");
        queue.addLast("2号");
        queue.addLast("3号");
        System.out.println(queue); // [1号, 2号, 3号]
        // 出队
//        System.out.println(queue.getFirst()); // 1号
        System.out.println(queue.removeFirst()); // 1号
        System.out.println(queue.removeFirst()); // 2号
        System.out.println(queue); // [3号]

        // 2、做一个栈   stack:栈
        LinkedList<String> stack = new LinkedList<>();
        // 入栈 压栈 (push)  public void push(E e) { addFirst(e); }
//        stack.addFirst("第1颗子弹");
        stack.push("第1颗子弹");
        stack.push("第2颗子弹");
        stack.push("第3颗子弹");
        stack.push("第4颗子弹");
        System.out.println(stack); // [第4颗子弹, 第3颗子弹, 第2颗子弹, 第1颗子弹]

        // 出栈  弹栈 pop    public E pop() { return removeFirst(); }
//        System.out.println(stack.removeFirst());
        System.out.println(stack.pop()); // 第4颗子弹
        System.out.println(stack.pop()); // 第3颗子弹
        System.out.println(stack.pop()); // 第2颗子弹
        System.out.println(stack); // [第1颗子弹]
    }
}