美文网首页
Java中的数据结构(jdk8)

Java中的数据结构(jdk8)

作者: 只道初见 | 来源:发表于2018-08-02 09:58 被阅读0次

1. 总体来说

java中主要的集合接口有Collection、Map。Collection有一个父接口,Collection有三个子接口List、Set、Queue。
数据结构灰常重要,所以,从架构体系到代码需要深入理解。另外,会盗一些图,哈哈。


java集合框架.png

2.List 接口的实现——ArrayList

ArrayList 是我们最常用的java数据结构之一,通过学习其源码,主要掌握其实现原理、扩容机制以及一些主要方法的使用与实现。最后自己动手实现一个简单的ArrayList。


ArrayList.png
2.1 基本了解ArrayList
  • ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。
  • ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。
  • ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。
  • 每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向ArrayList中不断添加元素,其容量也自动增长。自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容量。在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。
2.2 源码阅读理解
  • 属性
//  默认初始化容量为10
private static final int DEFAULT_CAPACITY = 10;
//一个空的对象数组用来存储实例
private static final Object[] EMPTY_ELEMENTDATA = {};
//使用默认构造函数时
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//当前数据对象,用transient 修饰,不参与序列化
transient Object[] elementData; // non-private to simplify nested class access
//当前数组长度,并非容量
private int size;
//数组的最大长度
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  • 构造方法

初始化带容量的构造器

/**
*初始化时带容量如果大于0就new一个相应大小的对象数组;容量等于
*0就调用预先定义好的空的对象数组;如果容量小于0则抛出 IllegalArgumentException
*/
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);
    }
 }

默认构造器,容量是10

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

带Collention对象的构造器

  1.把Collention对象转换成数组并且赋值给elementData,把数组的大小赋值给size
  2.判断是否为空数组如果是空数组则把预先声明好的赋值给elementData;否则再做深拷贝
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;
      }
  }
  • 主要方法(先主后次)

add方法
有两个,add(E e)和add(int index, E element)

/**
 *1)确保数组已使用长度(size)加1之后足够存下 下一个数据
 *2)修改次数modCount 标识自增1,如果当前数组已使用长度(size)加1后的大于当前的数组长度,则调用grow方法,增长数组,grow方法 
 *会将当前数组的长度变为原来容量的1.5倍。
 *3)确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。
 *4)返回添加成功布尔值。
 */
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

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);
}


/**
 * 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
 */
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);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}


/**
 * 在指定的位置插入元素
 * list. Shifts the element currently at that position (if any) and
 * any subsequent elements to the right (adds one to their indices).
 *
 * @param index index at which the specified element is to be inserted
 * @param element element to be inserted
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public void add(int index, E element) {
    //检查插入位置是否越界,如果index>size或则index<0 抛出IndexOutOfBoundsException异常
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}

remove方法
一共涉及到四个方法分别是,E remove(int index) 、boolean remove(Object o)、 fastRemove(int index)、clear() 。

/**
 * 移除指定位置的元素
 * Shifts any subsequent elements to the left (subtracts one from their
 * indices).
 *
 * @param index the index of the element to be removed
 * @return the element that was removed from the list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E remove(int index) {
    //边界检查
    rangeCheck(index);

    modCount++;
    //需要移除的数据
    E oldValue = elementData(index);
    //计算需要移动的数量
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
     //移除了一个元素,index后的元素都向前移动了一位,最后一个元素被孤立,需要被GC回收,这点effective java  中也有说明
    elementData[--size] = null; // clear to let GC do its work
    return oldValue;
}

/**
 * 遍历元素,通过匹配值,删除指定的对象
 * if it is present.  If the list does not contain the element, it is
 * unchanged.  More formally, removes the element with the lowest index
 * <tt>i</tt> such that
 * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
 * (if such an element exists).  Returns <tt>true</tt> if this list
 * contained the specified element (or equivalently, if this list
 * changed as a result of the call).
 *
 * @param o element to be removed from this list, if present
 * @return <tt>true</tt> if this list contained the specified element
 */
public boolean remove(Object o) {
    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;
}

/*
 * 实现快熟删除,原理是向前移动数组,再把最后一个元素置空,让GC回收
 * return the value removed.
 */
private void fastRemove(int index) {

    modCount++;
    //需要移动的元素个数
    int numMoved = size - index - 1;
    if (numMoved > 0)
  //把index后的元素向前复制移动           System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}

/**
 * 清空list,遍历数组把每个元素置空,让GC能够回收
 * be empty after this call returns.
 */
public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

相关文章

  • Java中的数据结构(jdk8)

    1. 总体来说 java中主要的集合接口有Collection、Map。Collection有一个父接口,Coll...

  • ArrayList源码解析

    最近在整理数据结构和算法,发现java的源码很优秀。就学习一下, 这里做个记录。我使用的是jdk8 熟悉java的...

  • java中treeset使用

    java中treeset使用 环境:jdk8 1:简介 这篇文章讲解java集合框架中实现set接口-TreeSe...

  • centos7搭建环境,部署springboot项目

    安装jdk8 安装jdk8,yum安装 通过java -version查看版本信息 列出java相关文件、查看安装...

  • java 数据结构(collections)

    JAVA中常用的数据结构(java.util. 中) java中有几种常用的数据结构,主要分为Collection...

  • JAVA Optional类

    jdk8 [理解、学习与使用 Java 中的 Optional] https://www.oschina.net/...

  • Java数据结构

    Java 数据结构 Java工具包提供了强大的数据结构。在Java中的数据结构主要包括以下几种接口和类: 枚举(E...

  • Java的HashMap总结

    数据结构 JDK7中的HashMap采用数组+链表的结构来存储数据 JDK8中的HashMap采用数组+链表或树的...

  • Java集合之ArrayList

    以下翻译自JDK8中的ArrayList源码 Java集合中的动态数组ArrayList是顶层接口List的实现,...

  • 3年Java程序员面试集锦-Java基础

    Java基础 1.HashMap的源码,实现原理,JDK8中对HashMap做了怎样的优化。 Hashtable、...

网友评论

      本文标题:Java中的数据结构(jdk8)

      本文链接:https://www.haomeiwen.com/subject/rrfjvftx.html