集合框架的使用

Java集合框架是一类用来存放元素的容器,主要分为实现了Map接口和实现了Collection接口的两类,前者存放的元素是一对key-value的映射,要求key唯一,后者存放的是单个元素,其中实现了Set接口的容器要求容器中的元素不可重复。

泛型

所谓泛型,就是类型参数话,集合框架下定义的容器希望不被局限于某一类元素,而是一套通用框架,可以存放除基本类型以为的其他类型。在集合容器变量声明时使用某一类型,那么此容器就只能存放这一类型的元素,并且容器中的元素可以调用这一类型元素可以调用的方法。

Collection类

collection.png

ArrayList

ArrayList是通过数组实现的List,具有快速随机查找的特点,但是删除元素和插入元素效率较低。常用的API有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int size();
public boolean isEmpty()
public boolean contains(Object o)
public int indexOf(Object o)
public Object[] toArray() //返回一个包含当前所有元素的数组
public int lastIndexOf(Object o)

public E set(int index, E element)
public E get(int index)
public void add(int index, E element) //在指定下标插入元素
public boolean add(E e)
public boolean remove(Object o) //删除指定下标的元素
public E remove(int index)
public void clear()
public boolean addAll(Collection<? extends E> c) //在当前列表后依次添加c中的元素

ArrayList实现了Cloneable接口,可以实现存储元素引用的浅拷贝,即两个容器中引用对象仍然相同,实现了Serializable接口,支持序列化和反序列化。

LinkedList

使用链表实现,每个节点item引用对象,和next,pre两个指针。LinkedList实现了Deque接口,可以从链表双端对链表进行操作。由于实现方式是链表,所以LinkedList具有插入和删除比较快,随机访问较慢的特点。LinkedList具有很多双端操作链表的API,可以认为如果不带显式的first和last方法,那么删除元素默认在链表尾部进行,添加元素在链表头部进行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;

Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
public boolean removeLastOccurrence(Object o)
public boolean removeFirstOccurrence(Object o)

public E pop()
public void push(E e)
public E pollFirst() //删除链表首部元素
public E pollLast()
public E peekFirst() //取得链表头节点
public E peekLast() //取得链表尾节点
public boolean offerFirst(E e)
public boolean offerLast(E e)

LinkedList不是线程安全的,如果有多个线程同时对LinkedList的结构进行修改(增加或者删除节点),有可能会导致链表出现环状。可以使用如下方法进行包装得到线程安全的List。

1
public static <T> List<T> synchronizedList(List<T> list)

Vector

Vector是线程安全的,有可能引起线程不安全的操作和获取相关Vector信息的值的方法都被synchronized修饰了。但是在不要求线程安全的场景下,推荐使用ArrayList代替Vector,性能更好。

Stack

Stack是继承自Vector的集合,具有后进先出的特点。

1
2
3
4
5
public E push(E item)
public synchronized E pop()
public boolean empty()
public synchronized int search(Object o)
public synchronized E peek()

HashSet

HashSet实现了Set接口,可以保证元素的容器中元素唯一,但是不保证有序。HastSet是通过HashMap实现的,保证容器中元素唯一的方式是,每次插入的元素实际是作为(key,value)中的key,value是一个Object对象,HashMap是可以保证存入元素key是唯一的,所以HashSet能够保证容器中的元素唯一。

1
2
3
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

HashSet同样是线程不安全的,如果需要在多线程场景中使用hashSet,推荐如下封装:

1
Set s = Collections.synchronizedSet(new HashSet(...));

LinkedHashSet

继承自HashSet,与HashSet相同,可保证元素唯一,使用LinkedHashMap实现,可以保证插入元素顺序可知。

TreeSet

实现了SortedSet接口,可以保证容器内元素不重复,可排序。

Map类

map.png
实现了Map接口的容器类用来存放的元素是一组key到value的映射关系,LinkedHashMap继承自HashMap,可以在HashMap的基础上保证存入顺序是可知的。

HashMap

LinkedHashMap

1
2
3
4
5
6
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}

LinkedHashMap实现这一功能的方式是,其中的每一个节点,都有两个指针,before和after,分别指向前一个插入节点,和后一个插入的节点。

LinkedhashMap是如何保证插入顺序有序的?重写了HashMap的newNode方法,将当前插入节点的before指针指向了插入前的尾节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
LinkedHashMap.Entry<K,V> p =
new LinkedHashMap.Entry<K,V>(hash, key, value, e);
linkNodeLast(p);
return p;
}
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
LinkedHashMap.Entry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
Map<String, Integer> scores = new LinkedHashMap<>();
scores.put("chemistry", 93);
scores.put("math", 98);
scores.put("biology", 92);
scores.put("english", 97);
scores.put("physics", 94);
scores.put("chinese", 99);
scores.put("geography", 95);
Iterator<Map.Entry<String, Integer>> iterator = scores.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> score = iterator.next();
System.out.println("subject: " + score.getKey() + " score: " + score.getValue());
}
}

map_answer.png

TreeMap

基于红黑树实现的,对可对key进行排序的NavigableMap。

reference:
https://zhuanlan.zhihu.com/p/34490361

文章作者: hohnor
文章链接: http://www.zhulk3.cn/2022/02/10/集合框架的使用/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 甜茶不贵