java集合知识归纳(一)

集合介绍

龚德浙

java SE阶段:

Java中常见API:集合、IO相关(基础使用、原理、应用场景)

多线程、网络、数据库(MySQL、Redis)、java虚拟机、设计模式、

spring、SPringMVC、mybatis等

项目:基于SSM整合的博客系统

集合

数组、链表、栈、队列等..通过数据结构,用来存储数据

集合在java.util包路径下

在该包路径下提供了很多的接口及实现类

注意:虚线对应的是接口,实现对应的是实现类

基于集合框架图可知:

顶层的接口:Collection和Map

Collection接口表示存储的是单个数据组成的集合

Map接口表示存储的是key-value的键值对的集合

相关接口介绍:

Collection接口主要有三个子接口:

List接口:允许存储重复的元素的集合

Set接口:不允许存储重复的元素的集合(去重)

Queue接口:可以重复。主要是用于存储数据,模拟队列(先进先出)模拟栈(先进后出)、优先级队列

Map接口:

存储的数据是以键值对形式存储

SortMap:对于元素进行排序

实现类特点:

List接口的实现类:

ArrayList:查询速度快,线程不安全,底层基于数组来存储元素,封装一个动态的Object[]数组,是一种顺序存储的集合(元素存储是按照插入顺序有序)

LinkedList:增删速度快,线程不安全,底层是一个双向链表实现,元素也是插入有序

Vector:线程安全,查询增删速度慢,已经被ArrayList替代

Set接口的实现类:

HashSet:底层数据结构是基于HashMap实现的,不按照集合中元素的顺序,即不能保证数据和插入的顺序一致,线程不安全

LinkedHashSet:底层是基于LinkedHashMap实现的,线程不安全,能保证数据的顺序和插入顺序一致

TreeSet:基于TreeMap集合实现,线程不安全的,数据是有序的(按照属性的特征排序)

Map接口的实现类:(存储的是键值对)

HashMap:底层是一个哈希表结构,线程不安全的,允许key-value 为null,key不能重复(哈希表结构相关),数据是无序的

Hashtable:和HashMap类似,底层是哈希表接口,线程安全的,key-value不能为null

LinkedHashMap:是HashMap的子类。可以保证数据是插入有序的

TreeMap:底层是二叉树:红黑树,线程不安全的,数据可以基于元素特征排序

在线JDK文档地址:在线文档-jdk-zh

Collection接口介绍

Collection接口提供的方法:


        /**
         * 添加单个元素
         * boolean add(E e)
         * 返回值Boolean类型  true:插入成功  false:插入失败
         */
        arrayList.add(23);

        ArrayList <Integer> list = new ArrayList <>();
        list.add(12);
        list.add(15);
        list.add(77);


        /**
         * 批量添加元素
         * boolean addAll(Collection<? extends E> c)
         * 返回值Boolean类型  true:插入成功  false:插入失败
         */
        arrayList.addAll(list);


        /**
         * 删除集合中元素
         * void clear()
         */
//        arrayList.clear();


        /**
         * 判断当前集合是否存在指定的元素o
         * boolean contains(Object o)
         * 返回值Boolean类型  true:存在当前元素  false:不存在当前元素
         */
        boolean b = arrayList.contains(12);
//        System.out.println(b);


        /**
         * 判断集合是否为空
         * boolean isEmpty()
         * 返回值Boolean类型  true:没有元素  false:至少存在一个元素
         */
        boolean empty = arrayList.isEmpty();
//        System.out.println(empty);


        /**
         * 通过迭代器来遍历集合
         * 迭代器是一种设计模式:作用是来遍历容器/集合而不暴露集合内部实现细节
         * Iterator<E> iterator()
         * 返回是Iterator类型对象
         * 该类型下提供方法:
         * hasNext():判断容器中是否还存在下一个元素
         * next():获取当前元素
         *
         * 23 12 15 77
         */
        Iterator <Integer> iterator = arrayList.iterator();
        while (iterator.hasNext()) {
            Integer value  = iterator.next();
            System.out.print(value+" ");
        }

        System.out.println();

        System.out.println("--------");
        /**
         *
         * for (:)
         * foreach遍历底层还是使用迭代器遍历
         * 格式是:for (集合中元素类型  元素别名 : 集合实例)
         */
//        for (Integer n :arrayList) {
//            System.out.print(n+" ");
//        }


        /**
         * 删除指定的元素对象o
         * boolean remove(Object o)
         * 返回是Boolean类型
         */
//        boolean remove1 = arrayList.remove(Integer.valueOf(77));

        /**
         * 删除指定位置index(下标位置) 的元素
         * E remove(int index)
         * 返回元素类型,将删除位置的元素返回
         */
//        Integer remove = arrayList.remove(1);

        ArrayList <Integer> list1 = new ArrayList <>();
        list1.add(15);
        list1.add(77);
        list1.add(33);
        /**
         * arrayList:23 12 15 77
         * list1    :15 77 33
         */
        /**
         * 保存当前集合中共有的数据进行保存(求两集合的交集)
         * boolean retainAll(Collection<?> c)
         *
         */
//        boolean b1 = arrayList.retainAll(list1);

        /**
         * 获取当前集合中元素的个数
         * int size()
         */
        int size = arrayList.size();
        System.out.println(size);
        
 

ArrayList工作原理及其实现

特点、需要通过源码底层实现查看实现逻辑

JDK源码查看:JDK版本 1.7.0_80版本

ArrayList集合使用:

特点:

1、ArrayList可以存放重复数据

2、ArrayList中元素存放和插入顺序一致

3、ArrayList中存放的数据是可以为null

4、ArrayList集合底层采用的是数组来存储数据

构造函数:

//无参构造
ArrayList <Integer> list = new ArrayList <>();
//通过指定集合容量大小来实例化
ArrayList <Integer> list1 = new ArrayList <>(100);
//通过Collection集合实例来实例化一个新集合
ArrayList <Integer> list2 = new ArrayList <>(list);

通过JDK源码来研究ArrayList的实现

1、关注继承关系

2、属性和默认值

3、构造函数

4、扩容机制、扩容时机

5、底层数据结构(数组、链表、队列、栈、哈希表...)

6、常见方法实现原理(add、get、remove)

继承关系:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList继承自AbstractList,AbstractList是抽象类,实现了List结构,它是一个数组队列,提供了相关的添加、删除、修改、遍历等基本功能实现,方法子类对方法复用,如果子类有特有功能可以重写父类的方法

ArrayList实现了List接口,List接口继承自Collection接口,在Collection接口提供的方法基础上,有一些新的方法提供,比如get、set、add等特有方法

ArrayList实现了RandomAccess接口,即提供了随机访问功能,为List提供快速访问的功能

ArrayList实现了Cloneable接口,即包含了函数clone(),能被克隆

ArrayList实现了Serializable接口,意味着ArrayList支持序列化,能通过序列化去传输(IO)

属性和默认值:

//默认的初始容量10
private static final int DEFAULT_CAPACITY = 10;

//空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};

//存储数据:使用的是数组,数组存储的数据类型是Object
    private transient Object[] elementData;
//用来记录存放数据的个数
    private int size;

ArrayList底层存储元素是使用数组

数组 elementData.length:表示当前数组容量,最大存储的数据个数 size:实际存放的数据个数

构造函数:

  //有参构造函数:通过指定初始容量initialCapacity来实例化ArrayList
	public ArrayList(int initialCapacity) {
        super();
        //参数合法性校验
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
        //实例化一个大小为initialCapacity数组并将数组赋值给elementData
        this.elementData = new Object[initialCapacity];
    }

    //无参构造函数  elementData赋值为空数组
    public ArrayList() {
       // ArrayList(DEFAULT_CAPACITY);
        super();
        this.elementData = EMPTY_ELEMENTDATA;
        //将默认值的赋值在add中完成
    }

    //通过集合来实例化ArrayList
    public ArrayList(Collection<? extends E> c) {
        //将集合转化为数组,直接赋值给elementData
        elementData = c.toArray();
        //将集合中已有元素的带下赋值给size
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

常见方法源码解析

add:添加元素

public boolean add(E e) {
        //考虑扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //将数据通过数组坐标插入到数据尾部,并对size+1
        elementData[size++] = e;
        return true;
    }

   private void ensureCapacityInternal(int minCapacity) {
        if (elementData == EMPTY_ELEMENTDATA) {
            //在添加第一个元素时,如果集合是通过无参构造实例时,会进入到if
            //在未指定集合容量时,默认情况下数组初始化大小为10
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

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

        // overflow-conscious code
        //minCapacity(size+1) > elementData.length,意味着数组空间不足,扩容时机
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

  //扩容点
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //扩容为原大小的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);//oldCapacity >> 1 => oldCapacity/2
        //对newCapacity进行边界的校正(不能小于minCapacity,不能大于MAX_ARRAY_SIZE)
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 将原有的集合数据拷贝到新容量为newCapacity的数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

ArrayList在未指定容量时,初始容量时10

modCount属性是版本控制器,也是ArrayList中的属性(继承自AbstractList中属性),和业务无关,仅仅是做版本控制,在集合进行变更时(修改、删除、添加)会自增1

扩容时机和扩容机制:当要插入数据的个数大于了数组容量,需要进行扩容,将容量大小变更为原大小的1.5倍,需要将原集合数据拷贝到新数组中

get():获取元素

 public E get(int index) {
        //检查查询位置的合法性 index <size
        rangeCheck(index);

        return elementData(index);
    }

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

	 E elementData(int index) {
        return (E) elementData[index];
    }

remove:删除元素

  public boolean remove(Object o) {
        //删除操作判断区分是否为null值,如果为null,判断相等使用==  如果不为null,判断相等使用equals
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

 //删除操作
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            //将index位置之后的数据全部前移一位
            System.arraycopy(elementData, index+1, elementData, index,numMoved);
          //Arrays.copyof() 拷贝和System.arraycopy 异同点、效率????
        //将最后一个位置置为null,并将size-1
        elementData[--size] = null; // clear to let GC do its work
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值