目录
集合框架
Collection接口框架
Iterator接口
List接口
List遍历
List示例
Map接口
Map遍历
Map示例
Set接口
Set遍历
线程安全集合
Java集合(java.util.*)是一非常重要的工具包:
- 其包含了常用的数据结构:集合、链表、队列、栈、数组、映射等;
- 集合可分为几个重要部分:List列表、Set集合、Map映射、工具类(Iterator、Enumeration、Arrays、Collections)。
集合框架
Java集合工具包框架图如下所示:
集合接口可分为Collection与Map两大类,而Collection又分为了List和Set两类:
- List:是一个有序队列(每个元素都有索引,从0开始),包括LinkedList、ArrayList、Vector、Stack。
- Set:是没有重复元素的集合,包括HashSet、TreeSet。
- Map:是一个映射接口(即key-value键值对),包括AbstractMap(抽象类)、HashMap、TreeMap和WeekHashMap等。
- Dictionary:是一个过时的抽象类(应使用Map接口替代)。
Collection接口框架
Collection是一个接口,主要分为List和Set。
Collection是高度抽象出来的集合接口,它包含了集合的基本操作:添加、删除、清空、遍历(读取)、是否为空、获取大小、是否保护某元素等等。
public interface Collection<E> extends Iterable<E> {
boolean add(E object);
boolean addAll(Collection<? extends E> collection);
void clear();
boolean contains(Object object);
boolean containsAll(Collection<?> collection);
boolean equals(Object object);
int hashCode();
boolean isEmpty();
Iterator<E> iterator();
boolean remove(Object object);
boolean removeAll(Collection<?> collection);
boolean retainAll(Collection<?> collection);
int size();
<T> T[] toArray(T[] array);
Object[] toArray();
};
Iterator接口
Iterator是集合的迭代器接口,用于遍历集合中的元素。
注意:若线程A在用Iterator在遍历集合时,其他线程修改了集合的内容,则线程A访问集合时会抛出ConcurrentModificationException异常。
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
};
List接口
List是继承于Collection的一个接口,表示有序队列,有四个实现类:
- ArrayList:数组队列(动态数组),随机访问高效,随机插入、删除低效;
- LinkedList:双向队列(可用作堆栈、队列与双端队列),随机操作低效;
- Vector:矢量队列(动态数组),线程安全的;
- Stack:堆栈,继承于Vector;
public interface List<E> extends Collection<E> {
// 除Collection接口外,增加以下接口
void add(int location, E object);
boolean addAll(int location, Collection<? extends E> collection);
E get(int location);
int indexOf(Object object);
int lastIndexOf(Object object);
ListIterator<E> listIterator(int location);
ListIterator<E> listIterator();
E remove(int location);
E set(int location, E object);
List<E> subList(int start, int end);
};
具体使用时,可:
- 对需快速插入、删除元素,使用LinkedList;
- 对需快速随机访问元素,使用ArrayList;
- 单线程操作使用ArrayList,多线程操作使用Vector(更好的方式参见‘线程安全集合’部分);
List遍历
List可以有多种遍历方式:
- 通过Iterator迭代器
Integer value = null;
Iterator iter = myList.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
- 通过for-each循环
Integer value = null;
for (Integer e:myList) {
value = e;
}
- 通过索引遍历(若是LinkedList,则非常低效)
Integer value = null;
for (int i=0; i<myList.size(); i++) {
value = (Integer)myList.get(i);
}
List示例
List的基本操作示例(以ArrayList为例):
class MyListData{
private Integer id;
private String name;
// ...
public Integer getId() { return id; }
public String getName() { return name; }
}
List<MyListData> myList = new ArrayList<>();
查找与遍历,可方便地使用stream实现:
MyListData findById(Integer nId){
return myList.stream().filter(d->d.getId()==nId).findFirst().orElse(null);
}
List<String> getAllName(){
return myList.stream().map(MyListData::getName).collect(Collectors.toList());
}
删除时,除通过remove(index)/remove(object)外(都需要先获知移除的元素);若是根据条件移除,更方便的方式是通过Iterator来实现:
MyListData removeData(Integer nId){
Iterator<MyListData> iter=myList.Iterator();
while(iter.hasNext()){
MyListData d = iter.next();
if(d.getId()==nId){
iter.remove();
return d;
}
}
return null;
}
Map接口
Map是映射接口,存储的是键值对(Key-Value),且不能包含重复的键。主要包括以下实现类:
- SortedMap:有序的Map;
- NavigableMap:继承于SortedMap,支持导航函数的Map;
- HashMap:基于‘拉链法’实现的散列表,一般用于单线程;
- Hashtable:基于‘拉链法’实现的散列表(线程安全的),一般用于多线程中;
- WeakHashMap:基于‘拉链法’实现的散列表,但其键是‘弱键’(不阻挡GC的垃圾回收);
- TreeMap:有序的散列表,基于红黑树实现;
public interface Map<K,V> {
void clear();
boolean containsKey(Object key);
boolean containsValue(Object value);
Set<Entry<K, V>> entrySet();
boolean equals(Object object);
V get(Object key);
int hashCode();
boolean isEmpty();
Set<K> keySet();
V put(K key, V value);
void putAll(Map<? extends K, ? extends V> map);
V remove(Object key);
int size();
Collection<V> values();
};
Map遍历
Map提供了forEach接口,以遍历元素;也能以键集、值集和键值集的形式遍历(设键String,值Integer类型):
- 通过forEach接口:
Integer value=null;
myMap.forEach((k,v)->
{
value=v;
});
- 通过entrySet遍历
String key = null;
Integer value = null;
Iterator iter = myMap.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
key = (String)entry.getKey();
value = (Integer)entry.getValue();
}
- 通过keySet遍历
String key = null;
Integer value = null;
Iterator iter = myMap.keySet().iterator();
while (iter.hasNext()) {
key = (String)iter.next();
value = (Integer)myMap.get(key);
}
- 通过values遍历
Integer value = null;
Collection c = myMap.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
Map示例
Map的基本操作示例(以ConcurrentHashMap为例)
class MyMapData{
private Integer id;
private String name;
private int count;
// ...
public Integer getId() { return id; }
public String getName() { return name; }
public void incCount() { ++count; }
}
Map<String,MyMapData> myMap = new ConcurrentHashMap<>();
基本操作可直接通过Map接口实现:
void AddData(String key, MyMapData data){
myMap.put(key, data);
}
MyMapData getData(String key){
return myMap.get(key); // 不存在时,返回null
}
通过forEach可依次处理元素:
void inceaseCount(){
myMap.forEach((k,v)-> {v.incCount();});
}
通过键集、值集和键值集的removeIf接口,可方便删除元素:
void removeByName(String strName){
myMap.values().removeIf(v->{
return v.getName().equals(strName);
});
}
Set接口
Set的实现类都是基于Map来实现的,且继承于Collection接口:
- HashSet:基于HashMap实现,不保证元素顺序,允许有null元素;
- TreeSet:基于TreeMap实现,是一个有序集合;
Set遍历
Set可通过如下方式遍历:
- 通过Iterator迭代器
Integer value = null;
Iterator iter = mySet.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
- 通过for-each循环
Integer value = null;
for (Integer e:mySet) {
value = e;
}
线程安全集合
早期的线程安全集合有Vector与HashTable,后来被ArrayList与HashMap替代,但后两者是非线程安全的,为此Collections中提供了同步的包装方法Collections.synchronizedXXX:
List<E> synArrayList = Collections.synchronizedList(new ArrayList<E>());
Set<E> synHashSet = Collections.synchronizedSet(new HashSet<E>());
Map<K,V> synHashMap = Collections.synchronizedMap(new HashMap<K,V>());
而1.8后在java.util.concurrent中新增了常用集合对应的线程安全集合,多线程环境下优先考虑。如:
- ConcurrentHashMap:线程安全的HashMap;
- CopyOnWriteArrayList:线程安全的ArrayList;
- CopyOnWriteArraySet:线程安全的ArraySet;
- 还有:ConcurrentSkipListMap、ConcurrentSkipListSet、ConcurrentLinkedQueue、ConcurrentLinkedDeque等