Java集合框架:全面解析核心代码与实战技巧

引言
Java集合框架是Java语言中非常重要的一部分,它提供了丰富的数据结构来存储和操作集合中的元素。理解Java集合框架的核心代码和实战技巧对于Java开发者来说至关重要。本文将全面解析Java集合框架,包括其核心数据结构、常用方法、以及在实际开发中的应用技巧。
Java集合框架概述
Java集合框架主要包括以下几个接口:
Collection
:表示一组对象,它提供了添加、删除、检查成员等基本操作。
List
:继承自
Collection
,表示有序集合,允许重复元素。
Set
:继承自
Collection
,表示无序集合,不允许重复元素。
Queue
:表示队列,用于在元素之间进行先进先出(FIFO)或后进先出(LIFO)操作。
Map
:表示键值对集合,用于存储键和值之间的映射关系。
核心数据结构
Java集合框架中常用的数据结构包括:
ArrayList
:基于动态数组实现,提供快速的随机访问。
LinkedList
:基于双向链表实现,提供高效的插入和删除操作。
HashSet
:基于哈希表实现,提供快速的查找和添加操作。
HashMap
:基于哈希表实现,提供快速的键值对存储和检索。
TreeSet
:基于红黑树实现,提供有序集合。
TreeMap
:基于红黑树实现,提供有序键值对集合。
常用方法
Java集合框架提供了丰富的常用方法,以下是一些常见的操作:
add(E e)
:添加元素。
remove(Object o)
:删除元素。
contains(Object o)
:检查元素是否存在。
size()
:获取集合大小。
isEmpty()
:检查集合是否为空。
clear()
:清空集合。
实战技巧
在实际开发中,以下是一些使用Java集合框架的实战技巧:
选择合适的数据结构:根据实际需求选择合适的数据结构,例如,如果需要快速随机访问,则选择
ArrayList
;如果需要快速插入和删除,则选择
LinkedList
。
使用泛型:使用泛型可以避免类型转换,提高代码安全性和可读性。
避免使用
==
比较对象:使用
equals()
方法比较对象是否相等。
使用迭代器:使用迭代器可以安全地遍历集合,避免并发修改异常。
核心代码解析
以下是一些Java集合框架的核心代码示例:
ArrayList
”`java
public class ArrayList
extends AbstractList
implements List
, 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);
}

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 contains(Object o) {
return indexOf(o) >= 0;
}

public Object clone() {
try {
ArrayList v = (ArrayList) super.clone();
v.elementData = Arrays.copyOf(elementData, elementData.length);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}

public boolean addAll(Collection c) {
modCount++;
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}

public boolean addAll(int index, Collection c) {
rangeCheckForAdd(index);
modCount++;
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew);
System.arraycopy(elementData, index, elementData, index + numNew, size – index);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}

public Iterator iterator() {
return new Itr();
}

public ListIterator listIterator() {
return new ListItr(0);
}

public ListIterator listIterator(int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}

public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}

public T[] toArray(T[] a) {
if (a.length < size) { return (T[]) Arrays.copyOf(elementData, size, a.getClass()); } System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) {
a[size] = null;
}
return a;
}

public boolean retainAll(Collection c) {
modCount++;
Objects.requireNonNull(c);
boolean modified = false;
for (int i = 0; i < size; i++) { if (!c.contains(elementData[i])) { fastRemove(i); i--; modified = true; } } return modified; } public boolean removeAll(Collection c) {
modCount++;
Objects.requireNonNull(c);
boolean modified = false;
for (int i = 0; i < size; i++) { if (c.contains(elementData[i])) { fastRemove(i); i--; modified = true; } } return modified; } public void clear() { modCount++; for (int i = 0; i < size; i++) { elementData[i] = null; } size = 0; } public boolean removeIf(Predicate filter) {
modCount++;
final int sizeBefore = size;
try {
for (int i = 0; i < size; i++) { if (filter.test(elementData[i])) { fastRemove(i); i--; } } } catch (Throwable e) { throwAsUnsupportedOperationException(e); } return sizeBefore != size; } public void forEach(Consumer action) {
Objects.requireNonNull(action);
final int size = this.size;
for (int i = 0; i < size; i++) { @SuppressWarnings("unchecked") E element = (E) elementData[i]; action.accept(element); } } public void replaceAll(UnaryOperator operator) {
Objects.requireNonNull(operator);
final int size = this.size;
for (int i = 0; i < size; i++) { elementData[i] = operator.apply(elementData[i]); } } public void sort(Comparator c) {
final int size = this.size;
if (size > 1) {
Object[] a = elementData;
int n = (size – 1) >>> 1;
Comparable mc = c instanceof Comparable ? (Comparable) c : null;
Arrays.sort(a, 0, n, (l, r) -> ((Comparable) l).compareTo(r));
int lo = 0, hi = size – n – 1;
while (lo < hi) { int lt = (lo + hi) >>> 1;
if (mc == null) {
Comparable lc = (Comparable) a[lo];
Comparable rc = (Comparable) a[hi];
int cmp = (lc.compareTo(rc) < 0) ? -1 : (lc.compareTo(rc) > 0) ? 1 : 0;
if (cmp > 0) {
hi = lt;
} else {
lo = lt + 1;
}
} else {
int cmp = c.compare(a[lo], a[hi]);
if (cmp > 0) {
hi = lt;
} else {
lo = lt + 1;
}
}
}
int loIndex = lo + 1;
int hiIndex = hi – 1;
int k = n;
while (lo < loIndex) { a[lo++] = a[k++]; } while (hiIndex < hi) { a[hiIndex++] = a[k++]; } } } public Spliterator spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, false);
}

private void writeObject(java.io.ObjectOutputStream s) throws IOException {
final int size = size;
s.defaultWriteObject();
s.writeInt(size);
for (int i = 0; i < size; i++) { s.writeObject(elementData[i]); } } private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); int capacity = 0; if (s.readInt() >= 0) {
capacity = s.readInt();
}
if (capacity < 0) { throw new InvalidObjectException("Invalid capacity: " + capacity); } this.elementData = new Object[capacity]; int size = 0; while (true) { Object o = s.readObject(); if (o == null) { break; } if (size == elementData.length) { int newCapacity = elementData.length + (elementData.length >> 1) + 1;
Object[] newElementData = new Object[newCapacity];
System.arraycopy(elementData, 0, newElementData, 0, elementData.length);
elementData = newElementData;
}
elementData[size++] = o;
}
this.size = size;
}

public static final class ArrayListSpliterator extends AbstractListSpliterator {
ArrayListSpliterator(ArrayList list, int origin, int fence, boolean parallel) {
super(list, origin, fence, parallel);
}

private ArrayListSpliterator create(Object o) {
return new ArrayListSpliterator<>(list, index, index >= 0 ? (index >= fence ? fence : Math.min(fence, list.size())) : fence, false);
}

public ArrayListSpliterator trySplit() {
int hi = (index >= 0) ? (index >= fence ? fence : Math.min(fence, list.size())) : fence;
int lo = index;
if (lo < hi) { index = lo; return create(hi); } return null; } public boolean tryAdvance(Consumer action) {
if (index >= 0) {
E e;
final ArrayList lst = list;
final int fence = this.fence;
try {
while (lo < fence) { e = lst.get(lo++); action.accept(e); if (lo >= fence) {
break;
}
}
} catch (Throwable ex) {
throwAsUnsupportedOperationException(ex);
}
if (lo < fence) { index = lo; return true; } } return false; } public void forEachRemaining(Consumer action) {
if (index >= 0) {
final ArrayList lst = list;
final int fence = this.fence;
try {
while (lo < fence) { action.accept(lst.get(lo++)); if (lo >= fence) {
break;
}
}
} catch (Throwable ex) {
throwAsUnsupportedOperationException(ex);
}
index = lo;
}
}
}

public static final class Itr implements Iterator {
int cursor; // index of next element to return
int lastRet = -1; // index of last returned element
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;
@SuppressWarnings(“unchecked”)
E next = (E) elementData[i];
lastRet = i;
return next;
}

public void remove() {
checkForComodification();
int lastRet = this.lastRet;
if (lastRet < 0) throw new IllegalStateException(); 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(); } } public static final class ListItr implements ListIterator {
int cursor; // index of next element to return
int lastRet = -1; // index of last returned element
int expectedModCount = modCount;

ListItr(int index) {
cursor = index;
}

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;
@SuppressWarnings(“unchecked”)
E next = (E) elementData[i];
lastRet = i;
return next;
}

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 (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
@SuppressWarnings(“unchecked”)
E previous = (E) elementData[i];
lastRet = i;
return previous;
}

public int nextIndex() {
return cursor;
}

public int previousIndex() {
return cursor – 1;
}

public void remove() {
checkForComodification();
int lastRet = this.lastRet;
if (lastRet < 0) throw new IllegalStateException(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (Index