【4-3】《Java中所有集合》——链表和二叉树、Collection、List、Set、Map、Iterator迭代器、集合在JDK9中的新特性

这篇博客深入探讨了Java集合框架,包括链表、二叉树的基本概念,以及Collection接口及其子接口List、Set的重点内容。详细介绍了ArrayList、Vector、LinkedList、HashSet、TreeSet等集合类的特性和使用场景,同时讲解了Map接口及HashMap、Hashtable、TreeMap的区别。还涵盖了JDK9中的集合新特性。
摘要由CSDN通过智能技术生成

集合

一、类集概述

集合是数据的容器。 java 对数据结构成熟的实现。

Collection和Map是同一级的,一个是单值存储,一个是双值存储,接下来的内容中会重点学习。

在这里插入图片描述

链表和二叉树都属于数据结构。

前期Java程序员不需要过于关注数据结构,因为Java内置了一套成熟的数据结构

二、链表和二叉树

1、链表

链表节点

class Node {
   
    Object data;
    Node next;
}

链表,linked list按特定的顺序链接在一起的抽象数据类型

  • 数组的优点

    • 存取速度快
  • 数组的缺点:

    • 事先必须知道数组的长度
    • 插入删除元素很慢
    • 空间通常是有限制的
    • 需要大块连续的内存块
    • 插入删除元素的效率很低
  • 链表的优点

    • 空间没有限制
    • 插入删除元素很快
  • 链表的缺点

    • 存取速度很慢
  • 可以通过练习编写链表的增删遍历代码对链表进行深入了解。

2、二叉树

在这里插入图片描述

链表只有下一个,二叉树有左下一个和右下一个

二叉树节点

class Node {
   
    Object data;
    Node left;
    Node right;
}

通常二叉树都是有序的,根节点向下分叉,存储的数据与根节点作比较,比根节点小存到左下,反之存到右下。之后每存储一个数据就按照这个存储顺序依次向下分叉。

  • 二叉树的遍历方式

    • 先序遍历

      先访问根节点,然后访问左节点,最后访问右节点,顺序:中左右

    • 中序遍历

      先访问左节点,然后访问根节点,最后访问右节点,顺序:左中右

    • 后序遍历

      先访问左节点,然后访问右节点,最后访问根节点,顺序:左右中

  • 可以通过练习编写二叉树的遍历代码对二叉树进行深入了解。

三、常见数据结构

数据存储常用结构有:栈、队列、数组、链表和红黑树。

1、栈

stack,又称堆栈,是一种限定存储的结构。限定仅在整个结构的尾部进行添加、删除操作的线性表。

特点:

  • 先进后出:例如将子弹压入弹夹之中,先压进去的子弹在下面,后压进去的子弹在上面,开枪时先弹出上面的子弹,后弹出下面的子弹。
  • 栈的入口和出口都是栈的顶端位置

此处有两个名词:

  • 压栈:存元素

  • 弹栈:取元素

栈在Java类集中用得不多。

2、队列

queue,就像排队,先排的先走。队列是一种特殊的线性表,只允许在表的一端插入,另一端删除。

特点:

  • 先进先出:例如火车过山洞,车头先进去、车尾后进去;车头先出来,车尾后出来。
  • 队列的入口、出口各占一侧。有单端队列和双端队列。

3、数组

Array,有序的元素序列。

特点:

  • 查找元素通过索引找,特别快。
  • 增删元素慢:需要创建新的数组,根据下标进行增加和删除,进行数据的移动

4、链表

linked list,由一系列节点node组成,每一个节点除了要存储数据,还要存储下一个节点的位置,像一个链链接起来。分为单向、双向链表和单向、双向循环链表。

特点:

  • 查找元素慢:依次查找
  • 增删元素快:只需要修改连接下个元素的地址

5、红黑树

二叉树:binary tree,每个节点不超过2的有序树。红黑树又称平衡二叉树。

特点:

  • 尽量保持平衡,不会将数据只存在一端

  • 速度特别快,趋近于平衡,查找叶子元素最少和最多次数不多于二倍

四、Collection接口(重点

单值存储从此处开始。

在整个 Java 类集中保存单值的最大操作父接口,里面每次操作的时候都只能保存一个对象的数据。此接口定义在 java.util 包中。单值存储。用得最多的是List和Set接口。

Collection接口的常用方法:

No. 方法名称 类型 描述
1 public booleanadd(Ee) 普通 向集合中插入一个元素
2 public boolean addAll(Collection<?extends E> c) 普通 向集合中插入一组元素
3 public void clear() 普通 清空集合中的元素
4 public boolean contains(Object o) 普通 查找一个元素是否存在
5 public boolean containsAll(Collection<?> c) 普通 查找一组元素是否存在
6 public boolean isEmpty() 普通 判断集合是否为空
7 public Iterator<E> iterator() 普通 为 Iterator 接口实例化
8 public boolean remove(Object o) 普通 从集合中删除一个对象
9 boolean removeAll(Collection<?> c) 普通 从集合中删除一组对象
10 boolean retainAll(Collection<?> c) 普通 判断是否没有指定的集合
11 public intsize() 普通 求出集合中元素的个数
12 public Object[] toArray() 普通 以对象数组的形式返回集合中的全部内容
13 <T>T[]toArray(T[] a) 普通 指定操作的泛型类型,并把内容返回
14 public boolean equals(Object o) 普通 从 Object 类中覆写而来
15 public int hashCode() 普通 从 Object 类中覆写而来
  • 为什么要学习集合?

    因为集合是Java中成熟的数据结构的实现,使用集合可以更合理地存储数据。便于对数据更好地进行管理。

1、List接口(重点

List中所有的内容都允许重复

对接口Collection的扩充方法:

No. 方法名称 类型 描述
1 public void add(int index,E element) 普通 在指定位置处增加元素
2 boolean addAll(int index,Collection<?extends E>c) 普通 在指定位置处增加一组元素
3 public E get(int index) 普通 根据索引位置取出每一个元素
4 public int indexOf(Object o) 普通 根据对象查找指定的位置,找不到返回-1
5 public int lastIndexOf(Object o) 普通 从后面向前查找位置,找不到返回-1
6 public List Iterator<E> list Iterator() 普通 返回 List Iterator
7 public List Iterator<E> listIterator(int index) 普通 返回从指定位置的 ListIterator 接口的实例
8 public E remove(int index) 普通 删除指定位置的内容
9 public E set(int index,E element) 普通 修改指定位置的内容
10 List<E> subList(int fromIndex,int toIndex) 普通 返回子集合
  • List中有许多实现类:ArrayList、Vector和LinkedList(双向链表)。

    Vector是ArrayList早期实现,ArrayList线程不安全,Vector线程安全。(线程后续学习)

1.ArrayList集合(重点

ArrayList是List接口的子类:有序、可重复。使用数组结构,增删慢、查找快。

创建数组:

ArrayList<Integer> data = new ArrayList<>();

接下来查看ArrayList的源码,我们看到ArrayList创建的数组,初始值为一个常量。

/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
   
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

再点进去这个常量,我们看到它是一个长度为0的数组。

/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
   };

**添加数据:**用上面的data调用add方法

data.add(100);
  • 存储时需要存储Integer类型数据,传入的int型会自动装箱为Integer类型数据。此时数组长度为0,若想存储数据,需要进行扩容,而add就对数据进行扩容操作

点开add源码,结果return的是true。

/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
   
    modCount++;
    add(e, elementData, size);
    return true;
}
  • 只要调用add方法,永远返回true。

再点开add中传入3个参数的add方法:

/**
* This helper method split out from add(E) to keep method
* bytecode size under 35 (the -XX:MaxInlineSize default value),
* which helps when add(E) is called in a C1-compiled loop.
*/
private void add(E e, Object[] elementData, int s) {
   
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}
  • 如果目前寸的数据和数组长度一致,说明存满了,此时用grow方法对其进行扩容,重新赋值给elementData。

最后点开grow方法,看到底是如何对数组进行扩容的。

/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero
*/
private Object[] grow(int minCapacity) {
   
    return elementData = Arrays.copyOf(elementData,
                                       newCapacity(minCapacity));
}

private Object[] grow() {
   
    return grow(size + 1);
}
  • 如果数组满了,最少给数组长度+1。定义一个新的数组长度,再使用Arrays.copyOf将旧数组的值,通过新的数组长度,赋值给旧数组。

查看newCapacity方法,用来计算新的长度:

/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by 50% if that suffices.
* Will not return a capacity greater than MAX_ARRAY_SIZE unless
* the given minimum capacity is greater than MAX_ARRAY_SIZE.
*
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero
*/
private int newCapacity(int minCapacity) {
   
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity <= 0) {
   
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return minCapacity;
    }
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
}

private static int hugeCapacity(int minCapacity) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值