pos机商城源码,ArrayList 源码解析

 新闻资讯  |   2023-07-02 12:10  |  投稿人:pos机之家

网上有很多关于pos机商城源码,ArrayList 源码解析的知识,也有很多人为大家解答关于pos机商城源码的问题,今天pos机之家(www.poszjia.com)为大家整理了关于这方面的知识,让我们一起来看下吧!

本文目录一览:

1、pos机商城源码

pos机商城源码

源码环境: JDK 1.8

首先介绍读源码的方法,有些构建的方法会将源码整体编译,造成卡顿,需要加大 Build process heap size。这里不将源码拷贝到src,具体见韩顺平的源码阅读配置视频:韩顺平源码视频,或者别人做的视频截图:自制截屏PPT。在写注释的时候,不要增删行数,以免 debug 时不匹配。

ArrayList 是一个可扩容的动态数组,通常每次扩大为原来的 1.5 倍。增删慢,查找快。

1 主要属性

默认大小为 10,使用 Object 类型的数组存储数据,size 表示数目,EMPTY_ELEMENTDATA 为空列表,另一个 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 用于懒加载。

private static final int DEFAULT_CAPACITY = 10;transient Object[] elementData;// 数组存储数据private int size;private static final Object[] EMPTY_ELEMENTDATA = {};// 空列表private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// 区别于空列表,用于懒加载2 构造器

一共三种构造器,无参构造器和大小为 0 的 Collection 构造器使用了懒加载,初始为空列表,可以节省内存,在 add 时才真正初始化 elementData。

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); } }public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;// 懒加载 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;// 懒加载 elementData } }3 add以及扩容3.1 add

一共有两个 add 方法,没有指定 index 会添加到最后,指定 index 的会在 index 处插入。

对于插入的方法,会首先将 index 及之后的元素向后移动 1 个位置,然后在 index 处放入 e。

public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index);// 将 element[index] 及之后的元素后移一位 elementData[index] = element; size++; }private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }/*** System 的方法,从 src[srcPos] 开始,移动到 dest[destPos],拷贝length个* 也就是从 src[srcPos] 到 src[srcPos + length - 1] 拷贝到 dest[destPos] 到 dest[destPos + length -1]。*/public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);3.2 addAll

addAll 方法同样有两个,对于单参数方法,采用的是 System.arraycopy 将 c 中的数据都添加到最后。

对于给定 index 的方法,则是两次移动,先将原来 index 及后面的元素,向后移动 numNew 位,对于集合 c 中的元素,插入index 位置。

public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }public boolean addAll(int index, Collection<? extends E> c) { rangeCheckForAdd(index); Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; }3.3 扩容相关

在正式执行添加操作前,需要调用 ensureCapacityInternal(int minCapacity) 来保证 elementData 的长度大于等于 minCapacity,否则扩容。

首先调用 calculateCapacity(Object[] elementData, int minCapacity),这里会处理初始化时懒加载的情况,如果不是就直接返回minCapacity。接着调用 ensureExplicitCapacity(int minCapacity) 判断是否需要扩容。如果扩容 grow(minCapacity),则首先 newCapacity 扩大为初始容量的 1.5 倍如果 minCapacity 大于 newCapacity,则 newCapacity 替换为 minCapacity。如果太大,超过了 MAX_ARRAY_SIZE,调用 hugeCapacity(int minCapacity)。调用 Arrays.copyOf(elementData, newCapacity) 返回新的 elementData。hugeCapacity(int minCapacity) 会判断是否 overflow,是的话抛出异常。 否则根据 minCapacity 和 MAX_ARRAY_SIZE 的大小返回 Integer.MAX_VALUE 或 MAX_ARRAY_SIZE。

private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {// 如果懒加载,则 return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; }private void ensureExplicitCapacity(int minCapacity) { modCount++; // 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 + (oldCapacity >> 1);// 扩容为 1.5 倍 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; }private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;4 remove

remove 包括两种,一种是给定位置 index,另一种是给定要删除的元素 o。

给定 index 删除后,如果删除的不是最后一个,需要将 index 后面的向前移动一位。

给定 o,对于 null 用 ==,对于非 null 用 equals。

从添加删除的过程来看,如果不是在末尾操作,都需要移动一些元素,平均复杂度为 O(n)。

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); elementData[--size] = null; // clear to let GC do its work return oldValue; }public boolean remove(Object o) { // 对于 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 rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }private void fastRemove(int index) {// 和remove的区别在于不用检查 index 是否越界,以及不用返回。 modCount++; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work }5 get/set

检查 index 符合范围后,直接在数组相应位置取出或者修改。

public E get(int index) { rangeCheck(index); return elementData(index); }E elementData(int index) { return (E) elementData[index]; } public E set(int index, E element) { rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; return oldValue; }6 迭代器

两种迭代器,迭代器 Itr,列表迭代器 ListItr。

public Iterator<E> iterator() { return new Itr(); }public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index);// 从 index 开始的 ListItr }public ListIterator<E> listIterator() { return new ListItr(0); }6.1 迭代器

Itr 实现了迭代器的 next 和 hasNext 以及 remove。

Itr 有三个成员变量:cursor 是下一个要访问的元素位置,lastRet 表示上次访问的元素位置,初始和删除后重置为-1, expectedModCount 负责检查是否抛出 ConcurrentModificationException。

hasNext 判断是否到达末尾, next 返回 cursor 处的元素,cursor向后移动, remove 调用 ArrayList 的方法删除 lastRet 处的元素。

private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; Itr() {} public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet);// 删除操作 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }6.2 列表迭代器

列表迭代器 ListItr 继承了 Itr,实现了 ListIterator。

ListIterator 除了 next 的方法,还包括 previous 相关方法,返回索引 nextIndex/previousIndex 的方法,添加 add 修改 set 的方法。

nextIndex 就是 cursor,而 previousIndex 就是 cursor - 1,所以next 返回 cursor 处的元素并后移 cursor,previous 返回 cursor-1 处的元素并前移 cursor。

add 在 cursor 处插入,set 修改 lastRet 处元素。具体则调用 ArrayList 方法来操作。

private class ListItr extends Itr implements ListIterator<E> { ListItr(int index) { super(); cursor = index; } public boolean hasPrevious() { return cursor != 0;// cursor 为 0 ,cursor-1 越界 } public int nextIndex() { return cursor; } public int previousIndex() { return cursor - 1; } @SuppressWarnings("unchecked") public E previous() { checkForComodification(); int i = cursor - 1; if (i < 0) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i; return (E) elementData[lastRet = i]; } public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e);// 修改操作 } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { int i = cursor; ArrayList.this.add(i, e);// 添加操作 cursor = i + 1; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } }

以上就是关于pos机商城源码,ArrayList 源码解析的知识,后面我们会继续为大家整理关于pos机商城源码的知识,希望能够帮助到大家!

转发请带上网址:http://www.poszjia.com/news/76687.html

你可能会喜欢:

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 babsan@163.com 举报,一经查实,本站将立刻删除。