java集合ArrayList
基于jdk_1.8.0
关于List,主要是有序的可重复的数据结构。jdk主要实现类有ArrayList(底层使用数组)、LinkedList(底层使用双向链表)
ArrayList:
(一)继承关系图
(二)源码解析
(1)关键字段
/**
* 默认初始容量
*/
private static final int DEFAULT_CAPACITY = 10; /**
* 用于空实例的共享空数组实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {}; /**
* 用于默认大小的空实例的共享空数组实例
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /**
*存储ArrayList元素的数组缓冲区
*/
transient Object[] elementData; //非私有以简化嵌套类访问 /**
* ArrayList的大小,也是下一个元素插入的位置
*/
private int size; /**
* 要分配的数组的最大大小
* 从hugeCapacity方法可以看到如果要分配的大小 > MAX_ARRAY_SIZE ,会返回Integer.MAX_VALUE
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 关于-8 ,网上说是数组元数据信息要占8个字节 字节和大小有哪门子关系,这个不够让人信服
(2)构造方法
/**
* elementData指向共享的默认空数组实例,将在添加第一个元素时扩展到DEFAULT_CAPACITY
*/
public ArrayList() {
//默认的空数组实例,主要是为了区别 new ArrayList(0)
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
} /**
* 构造一个initialCapacity大小的数组
*/
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(Collection<? extends E> c) {
//详见toArray实例方法
elementData = c.toArray();
//集合不为空
if ((size = elementData.length) != 0) {
//虽然elementData 是object[]类型的,但是它指向的类型不一定是Object[]
//造成的原因可能是Arrays.asList详情请戳https://www.cnblogs.com/liqing-weikeyuan/p/7922306.html
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
(3)常用方法
a. public boolean add(E e)
public boolean add(E e) {
// 为了确保数组不越界,所以允许的数组最小容量为size + 1
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
} private void ensureCapacityInternal(int minCapacity) {
// 由于calculateCapacity是静态方法,无法访问实例elementData变量
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
} /**
* 为啥要设计成静态方法,想不通
*/
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 若是通过默认构造方法构造,则返回DEFAULT_CAPACITY
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);
} /**
* 新的数组容量先按之前的1.5倍进行扩充
* 若扩充后的大小还不足以放下,则使用minCapacity
* 若minCapacity > MAX_ARRAY_SIZE,最大容量Integer.MAX_VALUE,否则内存溢出异常
* @param minCapacity
*/
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) {
// 容量超过Integer.MAX_VALUE
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
b. public void add(int index, E element)
/**
* 向指定位置添加元素,不常用,性能也不好
* @param index
* @param element
*/
public void add(int index, E element) {
rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!!
// [index, size -1] 向后移动一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
} /**
* A version of rangeCheck used by add and addAll.
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} /**
* 详见 a. public boolean add(E e) 不再展开
* @param minCapacity
*/
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
c. public boolean addAll(Collection<? extends E> c)
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // 详见a. add
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0; //??? 暂时没看懂
}
d. public boolean addAll(int index, Collection<? extends E> c)
/**
* 向指定位置添加集合元素
* @param index
* @param c
* @return
*/
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); //从index开始复制numMoved个元素到index + numNew (即[index, index + numMoved -1] 复制到[index + numNew, index + numNew + numMoved - 1]) System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0; //??? 没看懂
}
e. public E remove(int index)
/**
* 删除指定位置的元素
* @param index
* @return 被删除的元素
* @throws java.lang.ArrayIndexOutOfBoundsException
*/
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 + 1, size -1]元素 复制到 [index, size -2]
elementData[--size] = null; // clear to let GC do its work return oldValue;
} private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
} /**
* @throws java.lang.ArrayIndexOutOfBoundsException
*/
E elementData(int index) {
return (E) elementData[index];
}
f. public boolean remove(Object o)
/**
* 删除第一个值为o的元素
* @param o
* @return
*/
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;
} private void fastRemove(int 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
}
g. public boolean removeAll(Collection<?> c)
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
} // Objects.class
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
} private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r]; // 把没有包含的统一移动到数组的一端
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
if (r != size) {
// 前r个元素已经过滤完毕,这里只是简单的把[r, size-1]的元素复制移动到[w, w + size -r -1]
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
h. public E set(int index, E element)
public E set(int index, E element) {
rangeCheck(index); E oldValue = elementData(index); //强制转换成E
elementData[index] = element;
return oldValue;
}
i. public E get(int index)
public E get(int index) {
rangeCheck(index); return elementData(index); // 强制转化成E
}
j. public int indexOf(Object o)
/**
* 获取指定元素的下标
* @param o
* @return
*/
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
k. public int lastIndexOf(Object o)
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
l. public Iterator<E> iterator()
public Iterator<E> iterator() {
return new Itr();
} /**
* An optimized version of AbstractList.Itr
*/
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) //没有首先调用next(), 直接remove会抛IllegalStateException
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet); //详见e. public E remove(int index)
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) { //该异常什么情况下会被触发???
throw new ConcurrentModificationException();
}
} @Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
m. public ListIterator<E> listIterator()
public ListIterator<E> listIterator() {
return new ListItr(0);
} /**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
// 初始化游标位置,默认0
ListItr(int index) {
super();
cursor = index;
} // 只有第一个元素没有前继节点
public boolean hasPrevious() {
return cursor != 0;
} 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); // 详见 h. public E set(int index, E element)
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} /**
* 由于底层调用的是add(int index, E element), 还要有一次数组拷贝,性能不如 add(E element)
* @param e
*/
public void add(E e) {
checkForComodification(); try {
int i = cursor;
ArrayList.this.add(i, e); //详见b. public void add(int index, E element)
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
n. public ListIterator<E> listIterator(int index)
/**
* 指定游标
* @param index
* @return
*/
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index); // 详情请看 j. public ListIterator<E> listIterator()
}
o. public void forEach(Consumer<? super E> action)
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]); //使用见下面解析
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
} // Consumer.class
@FunctionalInterface // 使用该注解就表明可以使用lambda,只要接口只有一个抽象方法就可以用lambda
public interface Consumer<T> { void accept(T t); /**
* 可以看到andThen方法返回的是一个Consumer匿名类对象c
* 程序运行中如果不调用c.accept(),则什么也不会发生
* @param after
* @return
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); }; //重写了accept方法
}
} // TestConsumer.class
public void testAccept(String[] args) {
// jdk8 之前写法
Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s.toLowerCase());
}
}; // jdk8 lambda写法
Consumer<String> c = (s) -> System.out.println(s.toLowerCase());
c.accept("HELLO world!"); // hello world!
} public void testAndthen(String[] args) {
/**
* 通过这个例子可以看出首先调用了a.accept(),然后调用了b.accept()
*/
Consumer<String> a = (x) -> System.out.print(x.toLowerCase());
Consumer<String> b = (x) -> {
System.out.println("...andThen..." + x);
};
Consumer<String> c = a.andThen(b);
c.accept("HELLO world!"); // hello world!...andThen...HELLO world!
}
p. public void sort(Comparator<? super E> c) //TODO 先不展开
@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
q. public List<E> subList(int fromIndex, int toIndex)
/**
* 注意,该subList并没有new一个新的object[], 对subList对象的修改,都会作用到原大对象上
*/
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
} static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
} /**
* subList 并没有再new一个object[],而是复用
*/
private class SubList extends AbstractList<E> implements RandomAccess {
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size; SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
} public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
return oldValue;
} public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
} public int size() {
checkForComodification();
return this.size;
} public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
} public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = parent.remove(parentOffset + index);
this.modCount = parent.modCount;
this.size--;
return result;
} protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
parent.removeRange(parentOffset + fromIndex,
parentOffset + toIndex);
this.modCount = parent.modCount;
this.size -= toIndex - fromIndex;
} public boolean addAll(Collection<? extends E> c) {
return addAll(this.size, c);
} public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false; checkForComodification();
parent.addAll(parentOffset + index, c);
this.modCount = parent.modCount;
this.size += cSize;
return true;
} public Iterator<E> iterator() {
return listIterator();
} public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset; return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount; public boolean hasNext() {
return cursor != SubList.this.size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
} public boolean hasPrevious() {
return cursor != 0;
} @SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
} @SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = SubList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[offset + (i++)]);
}
// update once at end of iteration to reduce heap write traffic
lastRet = cursor = i;
checkForComodification();
} public int nextIndex() {
return cursor;
} public int previousIndex() {
return cursor - 1;
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} public void add(E e) {
checkForComodification(); try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}
};
} public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, offset, fromIndex, toIndex);
} private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
} private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+this.size;
} private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
} public Spliterator<E> spliterator() {
checkForComodification();
return new ArrayListSpliterator<E>(ArrayList.this, offset,
offset + this.size, this.modCount);
}
}
r. public <T> T[] toArray(T[] a)
/**
* 推荐使用 toArray(T[] a)
*/
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
} /**
* 如果a.length不足以放下所有的元素,则新建一个size大小的数组拷贝返回
* 如果a.length足够放下,遍历的时候小心空指针
* 推荐a.length == size new T[list.size()]
*/
public <T> T[] toArray(T[] a) {
if (a.length < size) // 传过来的数组大小不足以放下全部元素
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null; // ???没懂用意
return a;
}
s. 其它简单方法
/**
* 返回当前列表元素个数
* @return
*/
public int size() {
return size;
} /**
* 当前列表是否为空
* @return
*/
public boolean isEmpty() {
return size == 0;
} /**
* 当前列表是否包含元素o
* @return
*/
public boolean contains(Object o) {
return indexOf(o) >= 0; //详情请看 j. public int indexOf(Object o)
} /**
* 将elementData中未使用的空间 释放掉
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
} /**
* 清空所有引用
*/
public void clear() {
modCount++; // clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null; size = 0;
}
t. 序列化相关方法
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff
s.defaultReadObject(); // Read in capacity
s.readInt(); // ignored if (size > 0) {
// be like clone(), allocate array based upon size not capacity
int capacity = calculateCapacity(elementData, size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
ensureCapacityInternal(size); Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
} private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size); // Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
} if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
写在最后:
使用ArrayList进行存储的元素,务必要重写Object的equals方法。像IndexOf、lastIndexOf、remove等方法底层都是调用元素的equals方法进行比较;
通过get、set方法可以看出,ArrayList随机读写指定位置的元素速度非常快,但是remove、add等方法可能还需要有移动操作,故速度较慢;
通过remove indexOf 等方法可以看出ArrayList可以存储null值;
ArrayList.size 区间范围[0, Integer.MAX_VALUE], 超过Integer.MAX_VALUE,抛OutOfMemoryError。实际应用中还需要具体调整JVM内存大小;
通过代码可以看出,ArrayList任何方法均没有锁,故ArrayList是非线程安全的,若要在多线程环境下使用,要么调用者在外部同步要么参考Collections.synchronizedList(new ArrayList());
ListIterator增强了Iterator一些功能,添加了add、set、hasPrevious、previousIndex、previous、nextIndex方法,调用remove方法时,务必首先调用next或者previous;
subList 应该注意,对subList对象的任何修改都会作用到原对象上;
toArray,返回的是一个全新的对象,对其修改不会影响原list对象。
Q1:for-each与iterator使用场景
A1:如果一个集合或者数组需要更新元素(修改|删除),那么需要使用iterator或者普通for循环;
如果对于集合List使用iterator,建议优先选择使用listIterator;
如果只遍历集合元素,建议优先使用forEach或者支持并行的stream(jdk8以上),否则使用for-each。
java集合ArrayList的更多相关文章
- Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]
Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...
- Java基础系列 - JAVA集合ArrayList,Vector,HashMap,HashTable等使用
package com.test4; import java.util.*; /** * JAVA集合ArrayList,Vector,HashMap,HashTable等使用 */ public c ...
- Java集合---ArrayList的实现原理
目录: 一. ArrayList概述 二. ArrayList的实现 1) 私有属性 2) 构造方法 3) 元素存储 4) 元素读取 5) 元素删除 6) 调整数组容量 ...
- Java集合 -- ArrayList集合及应用
JAVA集合 对象数组 集合类之ArrayList 学生管理系统 斗地主案例 NO.one 对象数组 1.1 对象数组描述 A:基本类型的数组:存储的元素为基本类型 int[] arr={1,2,3, ...
- Java集合--ArrayList出现同步问题的原因
1 fail-fast简介 fail-fast 机制是java集合(Collection)中的一种错误机制.当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件.例如:当某一个线 ...
- java集合-- arraylist小员工项目
import java.io.*; import java.util.ArrayList; public class Emexe { public static void main(String[] ...
- Java集合ArrayList的应用
/** * * @author Administrator * 功能:Java集合类ArrayList的使用 */ package com.test; import java.io.BufferedR ...
- java集合-ArrayList
一.ArrayList 概述 ArrayList 是实现 List 接口的动态数组,所谓动态就是它的大小是可变的.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口 ...
- Java集合ArrayList源码解读
最近在回顾数据结构,想到JDK这样好的代码资源不利用有点可惜,这是第一篇,花了心思.篇幅有点长,希望想看的朋友认真看下去,提出宝贵的意见. :) 内部原理 ArrayList 的3个字段 priva ...
- Java集合-ArrayList源码解析-JDK1.8
◆ ArrayList简介 ◆ ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcc ...
随机推荐
- SQL优化技巧-批处理替代游标
通过MSSQL中的用户自定义表类型可以快速将需要处理的数据存储起来,生成新的临时表(这里使用变量表),然后根据表中字段进行批处理替代游标. 用户自定义表类型 0 --创建用户自定义表类型 1 Crea ...
- Egret 菜鸟级使用手册
首先,先安装好,然后,创建项目,弄好之后,在终端输入 egret run -a 开启服务 /*********************************华丽丽的分割线************** ...
- 【转】深入学习Redis(1):Redis内存模型
原文:https://www.cnblogs.com/kismetv/p/8654978.html 前言 Redis是目前最火爆的内存数据库之一,通过在内存中读写数据,大大提高了读写速度,可以说Red ...
- spring-data-jpa快速入门(一)——整合阿里Druid
一.概述 官网:https://projects.spring.io/spring-data-jpa/ 1.什么是spring-data-jpa Spring Data JPA, part of th ...
- Oracle的 EXEC SQL CONTEXT学习
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL杂记页 回到顶级页面:PostgreSQL索引页 [作者 高健@博客园 luckyjackgao@gmail. ...
- Deep Learning Tutorial 李宏毅(一)深度学习介绍
大纲 深度学习介绍 深度学习训练的技巧 神经网络的变体 展望 深度学习介绍 深度学习介绍 深度学习属于机器学习的一种.介绍深度学习之前,我们先大致了解一下机器学习. 机器学习,拿监督学习为例,其本质上 ...
- Restful和WeBAPI学习笔记
1.restful是基于无状态的,所谓无状态就是说客户端和服务端的每次通话都是独立的,不存在session和cookie之类的保存状态的机制,基于该协议可实现简单的curd操作, 其操作分为get\p ...
- Qt-网易云音乐界面实现-4 实现推荐列表和我的音乐列表,重要在QListWidget美化
来标记下这次我么实现的部分 这次我们来是试下这部分功能,来对比一下,左边是原生,右面是我写的,按着模仿的海可以哈,就有有的资源不是一样了,因为我连抠图都懒得扣了了 好了,现在就是我的是先过程了,主要教 ...
- Appium+python的单元测试框架unittest(1)(转)
unittest为python语言自带的单元测试框架,python把unittest封装为一个标准模块封装在python开发包中.unittest中常用的类有:unittest.TestCase.un ...
- 解决ScrollViewer嵌套的DataGrid、ListBox等控件的鼠标滚动事件无效
C# 中,两个ScrollViewer嵌套在一起或者ScrollViewer里面嵌套一个DataGrid.ListBox.Listview(控件本身有scrollviewer)的时候,我们本想要的效果 ...