集合之Collection知识梳理

文章详细介绍了Java集合框架中的迭代器Iterator,以及Collection接口和其子接口List的实现类,如ArrayList、LinkedList和Vector的特点。ArrayList的底层是数组,注重查询速度,而LinkedList基于双向链表,适合频繁的插入和删除。此外,还提到了Java中的Map接口和HashMap,以及线程安全的考虑。
摘要由CSDN通过智能技术生成

iterator(迭代器)

所有实现了Collection接口的集合类都有一个iterator()方法,用于返回一个实现了Iterator接口的对象,即可以返回一个迭代(用来遍历)

 

增强for循环的底层也是iterator ,

java.lang.Iterable接口,实现这个接口允许对象成为 “foreach” 语句的目标。

Java 5时Collection接口继承了java.lang.Iterable接口,因此Collection系列的集合就可以直接使用foreach循环遍历

for(元素类型 元素名: 集合名/数组名){
    访问元素;
}

Collection 集合 

 collection常用方法:

  • 1)add:添加单个元素
  • 2)remove:删除指定元素
  • 3)contains:查找元素是否存在
  • 4)size:获取元素个数
  • 5)isEmpty:判断是否为
  • 6)clear:清空
  • 7)addAll:添加多个元素
  • 8)containsAll:查找多个元素是否都存在
  • 9)removeAll:删除多个元素

----Collection: 单列集合,用来存储一个一个的对象

        ----List接口:存储有序的、可重复的数据。

                 ----Arraylist :作为List接口的主要实现类:线程不安全的,效率高:底

                 ----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高 

                 ----Vector:作为List接口的古老实现类:线程安全的,教率低,底层使用object[]
        ----Set接口:存储无序的、不可重复的数据-->高中讲的“集合 

                 ----HashSet:作为Set接口的主要实现类:线程不安全的:可以存储nulL值                                                     ----LinkedHashSet:作为HashSet的子类: 遍历其内部数据时,可以按照添加的顺序遍历

                 ----TreeSet :可以按照添加对象的指定属性,进行排序。

----Map接口:双列集合,用来存储一对(key - value)一对的数 -->高中函数: y = f(x,y)

         ----HashMap:作Map的主要实现类: 线程不安全的,效率高: 存储null的key和value

                ----LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历。

        ----TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序

        ----Hashtable:作为古老的实现类: 线程安全的,效率低:不能存储null的key和value

List

List集合所有的元素是以一种线性方式进行存储的,集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素 

List不仅继承了collection接口的方法,还有一些自己的方法

1、添加元素

void add(int index, E ele)
boolean addAll(int index, Collection<? extends E> eles)


2、获取元素

E get(int index)
List subList(int fromIndex, int toIndex) //返回从fromIndex到tolndex位置的子集合


3、获取元素索引

int indexOf(Object obj)  //返回obj在集合中首次出现的位置
int lastIndexOf(Object obj)  //返回obj在集合中末次出现的位置


4、删除和替换元素

E remove(int index)
E set(int index, E ele)  //设置指定index位置的元素为ele

List的实现类 

1.ArrayList

注意事项:

1.底层是由elementData数组来实现的

2.元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合

3.允许存储所有元素,包括null,ArrayList可以加入一个或者多个null

源码分析:

首先ArrayList有三种构造器,分别是无参构造器,一个int参数的构造器,一个Collection参数的构造器 

1.当调用无参构造器时,初始elementData容量为0

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
 }

2.调用int参数的构造器时,elementData的容量为int值的大小 

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

3. 调用Collection参数的构造器时,会将传入的c转为数组赋值给elementData,并且将size设置为c的长度

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

在添加元素时,会调用ensureCapacityInternal这个方法,确定是否需要扩容 

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

如果是第一次添加小于10个数据,elementData 扩容为默认值(10),然后进行数据添加,之后再添加,如果添加后长度没有超出数组最大限度,则直接添加,如果超出了,就要进行扩容,每次扩容都是创建一个长度为原数组1.5倍的新数组,让elementData指向新数组,然后再添加。

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

private static int calculateCapacity(Object[] elementData, int minCapacity) {
 	// 检测数据是否为空
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    	// 从默认值(10)与传入参数中选择最大的数进行返回
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity) {
	// 更新数自增
    modCount++;
    // 如果已经无法添加元素了(数组已满),就进行扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // 默认扩容1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
	// 最大值溢出处理
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
    	// 没有溢出就为int最大值
        newCapacity = hugeCapacity(minCapacity);
    // 转移数据
    elementData = Arrays.copyOf(elementData, newCapacity);
}

2.LinkedList 

注意事项: 

1.LinkedList底层是一个双向链表,使用Node包装了指针的信息与数据的内容

2.理论只受限于内存大小,所以不需要扩容操作

// 指针头,表示第一个节点
transient Node<E> first;

// 指针尾,表示最后一个节点
transient Node<E> last;

// node节点包装
private static class Node<E> {
   E item;
   Node<E> next;
   Node<E> prev;

   Node(Node<E> prev, E element, Node<E> next) {
       this.item = element;
       this.next = next;
       this.prev = prev;
   }
}
    public LinkedList() {
    }

   
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

在调用有参构造器时,会调用addAll方法,addAll方法的具体实现如图

假设LinkedList是有元素的。
请添加图片描述
那么经过addAll方法后改变它的结构
请添加图片描述
原来的LinkedList没有元素时
请添加图片描述

 在添加新元素时,用add()方法

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;
    // last为空说明原本链表没有元素,那么新增的元素就是第一个也是最后一个
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

3.Vector

1.Vector底层也是一个对象数组,protected objectl] elementData;
2. Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值