JAVA基础——集合


前言

此篇为记录Java基础中集合章节的有关知识点,主要包括Collection接口、Map接口下的实现类,以及他们之间的联系和区别


一、集合概要及框架体系

1、集合的理解

  • 集合跟数组一样,它也是用来保存数据的。那么为什么还会出现集合呢?那是因为数组有许多不足的地方。集合主要是两组(单列集合、双列集合)

2、数组的缺点

  • 长度开始时必须指定,而且一旦指定,不能更改。
  • 保存的数据类型必须为同一类型的元素。
  • 使用数组进行增加/删除元素时比较麻烦(每次都要进行扩容或者缩减)

3、集合的好处

  • 可以动态保存任意类型的对象或元素,使用方便
  • 提供一系列的操作对象的方法,不用自己实现它,可以直接使用,进行添加删除新元素方便。

4、集合的框架体系

1、Java的集合类很多,主要有Collection 接口和 Map 接口两大类,它们都继承了 Iterable 接口。
2、Collection接口 最常见的是Set 和List 接口;

  • Set接口中的常用实现类有:HashSet、TreeSet
  • List接口中的常用实现类有:ArrayList 、LinkedList、Vector,其中Vector的子类有常见的Stack(栈)类

3、Map接口中常见的实现类有HashMap、TreeMap、HashTable

  • HashMap常用的继承子类有LinkedHashMap
  • HashTable常用的继承子类有Properties

集合框架思维导图

二、Collection集合(单列集合)

Collection集合特点

  • Collection 实现子类可以存放多个元素,每个元素可以是Object
  • 有些Collection的实现类可以存放重复的元素,有些不可以
  • 有些Collection 的实现类是有序的(List),有些不是有序(Set)
  • Collection接口没有直接实现的子类,是通过它的子接口List和Set来实现的

Collection集合遍历元素方式

1、迭代器的遍历方式

//以hashSet为例:
        HashSet hashSet = new HashSet();
        Iterator iterator = hashSet.iterator();//1. 先得到 col 对应的 迭代器
        //使用 while 循环遍历,此循环可以使用 itit 快捷键
        //显示所有的快捷键的的快捷键 ctrl + j
        while (iterator.hasNext()) {//判断是否还有数据
            Object obj =  iterator.next();//返回下一个元素,类型是 Object
            System.out.println(obj);
        }
//当退出 while 循环后 , 这时 iterator 迭代器,指向最后的元素 iterator.next();
//NoSuchElementException 
//如果希望再次遍历,需要重置我们的迭代器 
iterator = hashSet.iterator();

注意:

  • 多次使用此迭代器时需要重置一下,因为每次循环完之后迭代器的
  • 在调用iterator.next()方法之前必须要调用iterator.hasNext()进行检测。若不调用,且下一条记录无效,直接调用it.next()会抛出NoSuchElementException异常。

2、增强for循环的遍历方式

//以HashSet为例
HashSet hashSet = new HashSet();
 for (Object obj : hashSet) {
   //此时可用快捷键 hashSet.I
            System.out.println(obj);
        }

1、List

List 接口是Collection接口的子接口。

  1. List集合内的元素是有序的(添加顺序和取出顺序一致)、且可以重复。
  2. List集合的每个元素都有其对应的顺序索引,即支持索引
  3. List容器中的元素是都对应一个整数型的序号记载其在容器的位置

Ⅰ. ArrayList底层结构和源码分析

一、注意事项

  1. ArrayList底层是由数组实现数据存储的。
  2. ArrayList基本等同于Vector,除了ArrayList是线程不安全的(执行效率高),而Vertor是线程安全的。不建议使用ArrayList.

二、底层操作机制源码分析
扩容机制结论:

  1. ArrayList 底层维护了一个Object类型的数组elementData。

  2. 当创建ArrayList对象时它有两种构造器,一种是无参构造,另一种是有参构造。当它创建时的长度为0时使用无参构造,则扩容elementData为10,如需要再次扩容,则是elementData的1.5倍。

  3. 当创建elementData给定一个长度时用有参构造,如需要扩容,则直接扩容为elementData的1.5倍。

  4. 在添加元素的时候,先调用特定的方法来确定是否要扩容(每次都要看是否需要扩容)

 public boolean add(E e) {
   
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

确定要扩容之后把需要扩容的大小设置为10,然后表示扩容的次数的变量自增1,如果大小不够,就调用grow()扩容(扩容到原来的1.5倍(length + length >> 1)),容量够了就不会调用grow()方法了。

private void ensureCapacityInternal(int minCapacity) {
   
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private void ensureExplicitCapacity(int minCapacity) {
   
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

grow()方法源码:

 private void grow(int minCapacity) {
   
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

Ⅱ Vector 底层结构和源码分析

一、注意事项

  • Vector集合跟ArrayList底层大致相同,只不过Vector跟ArrayList相比,它的线程安全(synchronized)
  • 它的扩容机制也跟ArrayList类似,在扩容时如果是没有给定大小,那么第一次扩容为10,但是第二次开始是按2倍扩容。
  • 与ArrayList相比,它的线程安全,但执行效率稍低。

二、debug源码

//底层同样跟ArrayList是elementData数组
public synchronized boolean add(E e) {
   
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
private void ensureCapacityHelper(int minCapacity) {
   
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
 private void grow(int minCapacity) {
   
        // overflow-conscious code
        int oldCapacity = elementData.length;
        /**二倍扩容机制
		*/
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
Vector子类——Stack(栈)

Ⅲ LinkedList底层结构和源码分析

一、注意事项

  • LinkedList中维护了两个属性,first和last ,first指向第一个节点Node,Last指向最后一个节点Node。
  • 每个Node节点中有prev(指向前一个节点)、next(指向下一个节点)、item(内容)这三个属性,最终实现双向链表
  • LinkedList底层维护了一个双向链表,而不是数组,所以添加和删除效率比ArrayList和Vector都高。

二、DebugLinkedList的添加元素 源代码

//DebugLinkedList的添加元素 源代码
 public boolean add(E e) {
   
       linkLast(e);
       return true;
   }
 void linkLast(E e) {
   
       final Node<E> l = last;
       final Node<E> newNode = new Node<>(l, e, null);
       last = newNode;
       if (l 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值