Java作为一门广泛应用于企业级应用开发的语言,其核心类库提供了丰富的API,极大地简化了编程工作。其中,JDK集合框架是Java核心类库的重要组成部分,它提供了强大的数据结构和算法支持。本文将深入解析Java核心类库源码,特别是JDK集合框架的核心技术,帮助读者全面掌握。
1. Java核心类库概述
Java核心类库是指Java标准库(Java Standard Edition API),它包含了Java编程语言中几乎所有常用的类和接口。这些类和接口被组织在多个包中,例如:
java.lang:包含Java语言的核心类,如Object、String、System等。java.util:提供集合框架、日期和时间处理、国际化和数学运算等功能。java.io:提供文件输入/输出操作、序列化等。java.net:提供网络通信功能,如URL、Socket等。
2. 集合框架概述
JDK集合框架是一个用于存储和操作对象的框架,它提供了多种数据结构,如列表、集合、映射和队列。集合框架的核心接口包括:
Collection:集合的根接口,表示一组对象。List:有序集合,允许重复元素。Set:无序集合,不允许重复元素。Queue:队列,用于元素先进先出(FIFO)的操作。Map:键值对映射,将键映射到值。
3. 集合框架核心技术解析
3.1. 集合框架实现类
Java集合框架提供了多种实现类,如ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等。以下是对这些实现类的源码解析:
3.1.1. ArrayList
ArrayList是基于动态数组实现的,它提供了快速的随机访问能力。以下是ArrayList的核心方法:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8683452581122892189L;
private static final int DEFAULT_CAPACITY = 10;
private transient Object[] elementData;
private int size;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ARRAY;
}
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ARRAY;
} else {
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
public boolean add(E e) {
modCount++;
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ARRAY) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
if (minCapacity - elementData.length > 0) {
grow(minCapacity);
}
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
if (newCapacity - MAX_ARRAY_SIZE > 0) {
newCapacity = hugeCapacity(minCapacity);
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) {
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
public E get(int index) {
rangeCheck(index);
return (E) elementData[index];
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}
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;
}
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;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1);
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = element;
size++;
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0) {
System.arraycopy(elementData, index + 1, elementData, index, numMoved);
}
elementData[--size] = null;
return oldValue;
}
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;
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
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;
}
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
modCount++;
int len = size;
for (int i = 0; i < len; i++) {
if (c.contains(elementData[i])) {
fastRemove(i);
i--;
len--;
}
}
return len != size;
}
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
modCount++;
int len = size;
for (int i = 0; i < len; i++) {
if (!c.contains(elementData[i])) {
fastRemove(i);
i--;
len--;
}
}
return len != size;
}
public void clear() {
modCount++;
for (int i = 0; i < size; i++) {
elementData[i] = null;
}
size = 0;
}
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
return v;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ArrayList)) {
return false;
}
ArrayList<?> that = (ArrayList<?>) o;
if (size != that.size()) {
return false;
}
Object[] elementData1 = elementData;
Object[] elementData2 = that.elementData;
for (int i = 0; i < size; i++) {
if (!Objects.equals(elementData1[i], elementData2[i])) {
return false;
}
}
return true;
}
public int hashCode() {
int h = 1;
int size = size;
for (int i = 0; i < size; i++) {
Object o = elementData[i];
if (o != null) {
h = 31 * h + o.hashCode();
}
}
return h;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
for (int i = 0; i < size; i++) {
if (i > 0) {
sb.append(", ");
}
Object o = elementData[i];
sb.append(o == this ? "(this Collection)" : o);
}
sb.append(']');
return sb.toString();
}
private void rangeCheck(int index) {
if (index >= size || index < 0) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last returned element
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
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();
}
E x = (E) elementData[i];
cursor = i + 1;
lastRet = i;
return x;
}
public void remove() {
checkForComodification();
int lastRet = this.lastRet;
if (lastRet == -1) {
throw new IllegalStateException();
}
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("Index: " + index);
}
return new ListItr(index);
}
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor > 0;
}
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();
}
E x = (E) elementData[i];
cursor = i;
lastRet = i;
return x;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
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 = lastRet + 1;
ArrayList.this.add(i, e);
cursor = i;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList<>(this, fromIndex, toIndex);
}
private 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 + ")");
}
}
static final class SubList<E> extends AbstractList<E> implements RandomAccess {
private final ArrayList<E> l;
private final int offset;
private final int size;
SubList(ArrayList<E> l, int fromIndex, int toIndex) {
this.l = l;
this.offset = fromIndex;
this.size = toIndex - fromIndex;
this.modCount = l.modCount;
}
public E get(int index) {
rangeCheck(index);
E e = l.get(offset + index);
this.modCount = l.modCount;
return e;
}
public E set(int index, E e) {
rangeCheck(index);
E oldValue = l.set(offset + index, e);
this.modCount = l.modCount;
return oldValue;
}
public int size() {
return size;
}
public void add(int index, E e) {
rangeCheckForAdd(index);
l.add(offset + index, e);
this.modCount = l.modCount;
}
public E remove(int index) {
rangeCheck(index);
E oldValue = l.remove(offset + index);
this.modCount = l.modCount;
return oldValue;
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize == 0) {
return false;
}
l.addAll(offset + index, c);
this.modCount = l.modCount;
return true;
}
public boolean remove(Object o) {
int i = indexOf(o);
if (i >= 0) {
remove(i);
return true;
}
return false;
}
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator() {
return listIterator(0);
}
public ListIterator<E> listIterator(int index) {
return new ListItr(index);
}
public List<E> subList(int fromIndex, int toIndex) {
return l.subList(fromIndex + offset, toIndex + offset);
}
private void rangeCheck(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
}
}
private void checkForComodification() {
if (modCount != l.modCount) {
throw new ConcurrentModificationException();
}
}
}
}
3.1.2. LinkedList
LinkedList是基于双向链表实现的,它提供了高效的插入和删除操作。以下是LinkedList的核心方法:
”`java
public class LinkedList
private static final long serialVersionUID = 8683452581122892189L;
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
public LinkedList() {
}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
public boolean add(E e) {
linkLast(e);
return true;
}
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size) {
linkLast(element);
} else {
linkBefore(element, node(index));
}
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0) {
return false;
}
int i = index;
Node<E> succ;
for (Object e : a) {
succ = node(i);
linkBefore((E) e, succ);
i++;
}
return true;
}
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) {
unlinkFirst(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) {
unlink(x);
return true;
}
}
}
return false;
}
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
for (
