常用的Java集合类包括List、Set、Queue、Map等。其中List、Set、Queue三个接口都继承了Collection接口,而Collection接口又继承了Iteratable接口。Java集合中只能保存对象,不能保存基本类型。泛型在集合中发挥了至关重要的作用,用来指定一个集合中元素的类型。
Collection:
Collection接口提供了集合类的一些公共方法,下面给出了Collection接口的定义。
public interface Collection<E> extends Iterable<E> {
int size(); // 集合内元素数量
boolean isEmpty(); // 集合是否为空
boolean contains(Object o); // 集合中是否包含o
Iterator<E> iterator(); // 返回集合的iterator
Object[] toArray(); // 将集合中元素以数组形式返回
/**
* 如果传入数组size足以装下集合中的元素,
* 则将元素装入后,返回传入数组本身,否
* 则创建新的数组,填充所有元素后返回
* 不对传入的数组做修改
*/
<T> T[] toArray(T[] a);
boolean add(E e); // 向集合添加元素
boolean remove(Object o); // 如果集合中存在o,则将其删除
boolean containsAll(Collection<?> c); // 当前集合是否包含集合c中的所有元素
boolean addAll(Collection<? extends E> c); // 将集合c中元素全部添加到当前集合
boolean removeAll(Collection<?> c); // 集合中的元素如果同时存在集合c中,则将这样的元素全部删除
boolean retainAll(Collection<?> c); // 集合中的元素如果不存在集合c中,则将这样的元素全部删除(集合交)
void clear(); // 清空当前集合
boolean equals(Object o); // 集合本身的比较
int hashCode(); // 集合本身的hashCode码
// 以及JDK1.8提供的四个方法:removeIf、spliterator、stream、parallelStream
}
AbstractCollection:
AbstractCollection是实现了Collection接口的抽象类,各出了Collection中许多方法的默认实现。同时AbstractCollection还覆写了Object的toString()方法。注意到AbstractCollection中有一个私有静态final的字段:MAX_ARRAY_SIZE,其值为整形最大值减8(Integer.MAX_VALUE - 8),限定集合中数组长度的最大值。
public abstract class AbstractCollection<E> implements Collection<E> {
// Collection中方法的默认实现...
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
}
Iterator:
Interator用于集合类的遍历、修改等操作,Collection接口继承了Iterable接口,说明了集合是可迭代的,能够生成一个Iterator对象。Iterator中有:hasNext()方法,判断是否还有下一个元素;next()方法,返回下一个元素(在hasNext()方法返回true时使用);remove()方法,删除下一个元素(hasNext()方法返回true时使用)。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer i = iterator.next();
if (i % 2 == 0)
iterator.remove();
System.out.print(i + " "); // 1 2 3 4
}
System.out.println();
System.out.println(list); // [1, 3]
}
}
List:
List列表以顺序结构存储数据。Java中两种常用的列表有基于数组实现的ArrayList和基于双向链表实现的LinkedList。ArrayList能够高效的在指定位置上进行访问,由于数组长度不可变,添加元素时,若数组不足以容纳,则需要开辟新的数组,将原数组中元素复制到新数组,再进行添加。扩容策略是,每次增加1/2的容量。而删除操作,会导致大量数组元素的移动。当删除一个元素(除了最后一个)后需要将删除位置之后的所有元素向前移动一个位置。ArrayList更适合高访问量、低修改(插入or删除)量的情况。LinkedList底层采用双向链表,能够高效的进行插入和删除操作,而访问元素效率低下,需要遍历操作。ArrayList适合修改量高、而访问量低的情况。LinkedList同时实现了Queue/Deque接口,即能用作栈,又能用作双端队列。
Map:
Map提供了基于Key-Value(键值对)的存储,底层数据结构是哈希表,能够根据hash计算,确定某个key的存储位置。哈希表会发生碰撞,一般有链地址法和开放地址法解决冲突。HashMap采用链地址法解决冲突,并且每个槽位上会进行链表和红黑树的相互转换(链表过长访问效率低,但实际上如果hash算法适当,转换成红黑树的情况很少)。LinkedHashMap在HashMap的基础之上,维护了一条按插入顺序的双向链表,当accessOrder设置为true时,该链表还会在发生访问时,调整链表结构。此特性能够帮助我们实现一个提供LRU缓存功能的哈希表。TreeMap的底层数据结构是红黑树(与算法导论中的算法一致),每个节点存储key、value两个域。TreeMap的特性就是红黑树的特性,插入、删除、查找能够在lgn时间内完成,并且所有元素按照二叉树的中序遍历有序。
Set:
Set表示一组不重复集合,Java中的Set底层数据结构就是Map,利用了Map的键集合来存储数据,以保证数据的不重复。而LinkedHashSet利用的是LinkedHashMap。HashSet使用的是HashMap、LinkedHashSet使用的是LinkedHashMap、TreeSet使用的是TreeMap,而他们的Value值存储的都是同一个静态Object变量。
Queue:
队列是一种先进先出(FIFO)数据结构,允许在一头插入元素,另一头取出元素,非常适合生产者-消费者的场景。LinkedList实现了双端队列的功能。PriorityQueue优先队列,底层是用数组实现的最小(大)堆,数组能够进行扩容操作,并且在每次插入后进行调整以保持最小(大)堆性质,因此能够保证队头永远是优先级最高的元素。
本文深入介绍了Java集合框架的核心组件,包括List、Set、Queue、Map等接口及其具体实现类的特点和应用场景,对比了不同集合类在性能上的优劣。
16万+

被折叠的 条评论
为什么被折叠?



