java集合(一)ArrayList和LinkedList

103 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

简介

集合又称容器。是Java中对数据结构(数据存储方式)的具体实现。

我们可以利用集合存放数据,也可以对集合进行新增、删除、修改、查看等操作。

集合中数据都是在内存中,当程序关闭或重启后集合中数据会丢失。所以集合是一种临时存储数据的容器。

JDK中集合结构图

集合作为一个容器,可以存储多个元素,但是由于数据结构的不同,java提供了多种集合类。将集合类中共性的功能,不断向上抽取,最终形成了集合体系结构。

List接口和Set接口

List和Set的父接口

  1. List接口:存储有序, 可重复数据。

  2. Vector:List的实现类,底层为可变长度数组实现。所有方法都是同步操作(线程安全),每次扩容成本增长。新数组长度为原数组长度的2倍

  3. ArrayList:List的实现类,底层为可变长度数组实现。所有方法都是非同步操作(非线程安全的),以1.5倍的方式在扩容。常用于: 查询较多的情况

  4. LinkedList:List的实现类,双向非循环链表的实现。常用于: 删 增 较多的情况

Set接口:存储无序,不可重复数据。

  1. HashSet:Set实现类,底层是HashMap 散列表(数组+链表+(红黑树 jdk1.8及之后))。所有添加到 HashSet 中的元素实际存储到了HashMap的key中

  2. LinkedHashSet:HashSet子类. 使用LinkedHashMap来存储它的元素,存储的值插入到LinkedHashMap的可以key中, 底层实现(数组+链表+(红黑树 jdk1.8及之后) + 链表), 可以记录插入的顺序

  3. TreeSet:Set实现类,底层是TreeMap(红黑树实现), 存入到TreeSet中的元素, 实际存储到了TreeMap中, 根据存储元素的大小可以进行排序

2.2 Map接口

Map:独立的接口。每个元素都包含Key(名称)和Value(要存储的值)两个值。

  1. HashMap:Map实现类, 对散列表 (数组+链表+(红黑树Java8及之后))的具体实现,非同步操作(非线程安全的)。存储时以Entry类型存储(key, value)

  2. LinkedHashMap: HashMap的子类,是基于HashMap和链表来实现的。在hashMap存储结构之上再添加链表, 链表只是为了保证顺序

  3. TreeMap:Map实现类, 使用的不是散列表, 而是对红黑树的具体实现。根据key值的大小, 放入红黑树中, 可实现排序的功能(key值大小的排序)

  4. HashTable:Map实现类, 和HashMap数据结构一样,采用散列表(数组+链表+(红黑树 jdk1.8及之后))的方法实现, 对外提供的public函数几乎都是同步的(线程安全)。

常用的集合: ArrayList, HashMap, HashSet

ArrayList

ArrayList 实现了List接口, 底层实现可变长度数组。存储有序、可重复数据, 有下标

实例化

常用向上转型进行实例化。绝大多数集合都支持泛型,如果不写泛型认为泛型是< object >,使用集合时建议一定要指定泛型。

List<泛型类型> 对象 = new ArrayList<>();

内存结构图

常用API

public class TestArrayList {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    //按照下标添加
    list.add("aa");
    //添加到指定的位置
    list.add(1, "bb");
    //查看元素个数
    int size = list.size();
    //根据指定的下标修改
    list.set(0, "aaa");
    //判断
    int bb = list.indexOf("bb"); //元素存在, 返回元素的下标. 不存在, 返回-1
    boolean b = list.contains("bb"); //元素存在, 返回true. 不存在, 返回false
    //删除
    list.remove(0); //根据下标删除
    list.remove("bb"); //根据指定元素删除
    //更新
    list.set(1, 65); 
      
    //查询
    for (String s : list) {
      System.out.println(s);
    }
    for (int i = 0; i < size; i++) {
      System.out.println(list.get(i));
    }
  }
}

LinkedList

介绍

LinkedList是Java中对双向非循环链表的实现。实现了List接口。

具有ArrayList所有常用方法,额外还添加了头尾操作方法(实现了Deque接口),这些方法在List接口中是不存在的,所以如果希望使用这些头尾操作方法,实例化时不用向上转型。

实例化语法

LinkedList<泛型>  对象= new LinkedList<>();

常用API

ArrayList里面常用API在LinkedList中都可以使用。

下面的演示为LinkedList比ArrayList多的常用方法。

public class TestLinkedList {
  public static void main(String[] args) {
    LinkedList<String> linkedList = new LinkedList<>();
    linkedList.addFirst("aa");
    linkedList.addLast("bb");
​
    //获取头结点 没有头结点 java.util.NoSuchElementException
    String first = linkedList.getFirst();
    System.out.println(first);
    //获取尾结点 没有尾结点 java.util.NoSuchElementException
    String last = linkedList.getLast();
    System.out.println(last);
​
    //获取头结点 没有头结点 返回 null
    String s = linkedList.peekFirst();
    System.out.println(s);
    //获取尾结点 没有尾结点 放回 null
    String s1 = linkedList.peekLast();
    System.out.println(s1);
​
    //删除头结点 没有头结点 java.util.NoSuchElementException
    String s2 = linkedList.removeFirst();
    System.out.println(s2); //被删除结点中的值
    //删除尾结点 没有尾结点 java.util.NoSuchElementException
    String s3 = linkedList.removeLast();
    System.out.println(s3);//被删除结点中的值
    
    //删除头结点 没有头结点 返回 null
    String s4 = linkedList.pollFirst();
    System.out.println(s4);
    //删除尾结点 没有尾结点 放回 null
    String s5 = linkedList.pollLast();
    System.out.println(s5);
​
  }
}

Java中栈和队列的实现类

Vector过时了,被ArrayList替代了,Stack也过时了

public  class Stack<E> extends Vector<E>  

Deque和Queue的实现类 1.ArrayDeque 顺序栈 数组 2.LinkedList 链栈 链表

 public interface Queue<E> extends Collection<E>
 public interface Deque<E> extends Queue<E>

早期的栈结构实现类 Stack

public class Test1 {
    public static void main(String[] args) {
        Stack<String> stack =new Stack<String>();
        // 入栈方法
        stack.push("马云");
        stack.push("马化腾");
        stack.push("马斯克");
      
        // 跳栈 弹栈 取出栈顶元素
        String pop = stack.pop();
        System.out.println(pop);
        System.out.println(stack);
    }
}

Queue单端队列

public class Test2 {
    public static void main(String[] args) {
        Queue<String> q=new LinkedList<String>();
        // 入队方法
        q.offer("张三丰");
        q.offer("张翠山");
        q.offer("张无忌");
​
        System.out.println(q);
​
        // 出队方法 取出队首
        String poll = q.poll();
        System.out.println(poll);
        System.out.println(q);
​
    }
}

Deque双端队列

public class TestLinkedList2 {
    public static void main(String[] args) { 
        //摞盘子
        Deque<String> deque1 = new LinkedList<String>();
        deque1.offerFirst("盘子1");//队首存值
        deque1.offerLast("盘子2");//队尾存值
        deque1.pollFirst();//队首取值
        deque1.pollLast();//队尾取值
        
        System.out.println(deque1.size());
  
    }
}