Java将一些基本的和使用频率极高的数据结构进行封装和增强后,作为集合类提供出来。理解和掌握好集合类可以提高我们的编程能力。
集合体系
从图中可以看到,Java的集合体系又分为两个相对独立的体系:Collection和Map。Collection用于存放独立的对象(不能存放基本数据类型),称为单列集合;Map用于存放映射关系(也就是键值对),称为双列集合。
接口Collection<E>常用方法
// 增
boolean add(E) // 添加一个类型为E的元素
boolean addAll(Collection<? extends E> c) // 添加指定Collection中的所有元素
// 删
void claer()// 移除所有元素。
boolean remove(Object o) // 移除指定元素。(参数列表没有使用泛型,为什么?)
boolean removeAll(Collection<?> c) // 移除所有在指定collection中包含的元素。
boolean retainAll(Collection<?> c) // 保留指定collection中包含的元素,其余的元素删除(取交集)
// 查
boolean contains(Object) // 判断是否存元素
boolean containsAll(Collection<?> c) // 判断是否包含指定collection中的所有元素
boolean isEmpty() // 判断集合是否为空
int size() // 返回集合中元素的个数
// 获取
Iterator<E> iterator() // 返回此集合的迭代器
Object[] toArray() // 返回一个包含集合中所有元素的数组
接口List有角标的存在,有一些特有方法
// 增
boolean add(index, E) // 在指定位置添加元素
boolean addAll(index,Collection<? extends E>) // 在指定位置添加指定Collection中的所有元素
// 删
boolean remove(index) // 移除指定位置的元素。
// 改
E set(index, E) // 更改指定位置的元素
// 获取
E get(int index) // 获取指定位置的元素
int indexOf(Object o) // 获取指定元素的角标,从头开始查找
int lastIndexOf(Object o) // 获取指定元素的角标,从尾开始查找
ListIterator<E> listIterator() // 返回此集合的列表迭代器
List<E> subList(int head, int end) // 获取从head到end的元素(不含尾)
Iterator 与 ListIterator
Iterator:只有获取元素的功能,如果用Iterator迭代时对集合进行增删操作,会报并发访问异常。
ListIterator:List特有。既有获取也有修改元素的功能,在迭代过程中可用其特有方法对集合进行操作。
元素的比较
List:比较元素用的是equals()方法
HashSet:先用hashCode()方法比较,如果一样再用equals()比较
TreeSet:用compareTo()或者比较器,如果元素同时实现了Comparable和Comparator接口,则优先使用比较器
内存泄漏
在向HashSet集合添加元素后,如果修改了元素中参与hashCode()运算的成员变量的值,有可能会造成无法将元素移出集合的情况。
Map<K, V>常用方法
// 增、该
V put(K key, V value) // 添加一个元素
void putAll(Map<? extends K,? extends V>) // 添加指定Map中的所有元素
// 删
void claer() // 移除所有元素。
V remove(Object key) // 移除一个元素
// 查
boolean containsKey(Object key) // 判断是否包含键
boolean containsValue(Object value) // 判断是否包含值
boolean isEmpty() // 判断集合是否为空
int size() // 返回集合中元素的个数
// 获取
V get(Object key) // 获取值
Collection<V> values() // 返回所有值
Set<K> keySet() // 返回所有键
Set<Map.Entry<K,V>> entrySet() // 返回所有键值对
遍历Map
Map没有迭代器,所以没有直接遍历Map的方法。要遍历Map有两种方式:
1、先用keySet()获得所有键,再用这些键去获取值:
Set keys = map.keySet();
for (Object key : keys) {
Object value = map.get(key);
}
2、用entrySet()获得所有键值对:
Set entries = map.entrySet();
for (Map.Entry entry : entries) {
Object key = entry.getKey();
Object value = entry.getValue();
}
常用实现类
List
ArrayList:底层是数组,线程不同步
LinkedList:底层数据结构是链表,线程不同步
Set底层使用的是Map
HashSet:底层数据结构是哈希表,线程不同步
TreeSet:底层数据结构是二叉树,线程不同步
Map
Hashtable:底层数据结构是哈希表,键、值均不能为null,线程同步
HashMap:底层数据结构是哈希表,键、值可为null,线程不同步
TreeMap:底层数据结构是二叉树,键有序,线程不同步
同步集合
大多数的集合都是线程不同步的。如果需要线程同步,可以同过Collections.synchronizedXXX()方法转换得到。
Set和Map中的加载因子
创建Set集合和Map集合时有一个可选参数:加载因子,默认为0.75。
加载因子 = 元素个数 / 集合容量。
当加载因子达到指定数值后,集合会自动扩容。
Collection 与 Collections
Collection位于java.util包下,是单例集合的根接口。
Collections是工具类,针对集合提供了一系列的静态方法对集合进行操作,利用Collections提供的方法可以方便地实现对集合的增删查改、排序、线程安全化(原理:定义一个类,将集合所有的方法加同一把锁后返回。)等操作。
还有一个常用的工具类Arrays,可通过Arrays.asList()实现数组到集合的转换,通过toArray()实现Collection集合到数组的转换。
(文章所用图片来自互联网)