一、Java集合框架
1.将集合的接口与实现分离
2.Collection接口
pubilc interface Collection<E>{
boolean add(E element);
Iterator<E> iterator();
}
public interface Iterator<E>{
E next();
boolean hasNext();
void remove();
default void forEachRemaining(Consumer<? super E> action;
}
Collection<String> c = ...;//迭代器样例
Iterator<String> iter = c.iterator();
while(iter.hasNext())
{
String element = iter.next();
do something;
}
2.1 迭代器
for each循环可以与任何实现了Iterable接口的对象一起工作。Java迭代器查找操作与位置变更时紧密相连的,应该将Java迭代器认为是位于两个元素之间。当调用next时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。Remove方法则会删除上次。
Java SE8 中,甚至不用写循环。可以调用forEachRemaining方法并提供一个lambda表达式。
iterator.forEachRemaining(element -> do something with element);
对next方法和remove方法的调用具有互相依赖性。如果调用remove之前没有调用next将是不合法的。
2.3 API
java.util.Collection<E> 1.2
Iterator<E> iterator() //返回一个用于访问集合中每个元素的迭代器
int size()
boolean isEmpty()
boolean comtains(Object obj)
boolean containsAll(Collection<?> other)
boolean add(Object obj)
boolean addAll(Collection<? extends E> other)
boolean remove(Object obj)
boolean removeAll(Collection<?> other)
default boolean removeIf(Predicate<? super E> filter)
void clear()
boolean retainAll(Collection<?> other)
Object[] toArray()//返回这个对象的数组
<T> T[] toArray(T[] arrayToFill)//返回这个集合的对象数组,
//如果arrayToFill足够大则将集合中的元素填充,其余为null,否则分配一个新数组。
2.4 集合框架中的接口
集合有两个基本接口:Collection和Map。
由于映射包含键值对,所以要用put方法来插入,从映射中读取值则要使用get方法
V put(K key, V value); V get(K key);
二、具体的集合
集合类型 | 描述 |
---|---|
ArrayList | 可以动态增长和缩减的索引序列 |
LinkedList | 可以在任何位置进行高效地插入和删除操作的有序序列 |
ArrayDeque | 用循环数组实现的双端队列 |
HashSet | 没有重复元素的无序集合 |
TreeSet | 有序集 |
EnumSet | 包含枚举类型值的集 |
LinkedHashSet | 可以记住元素插入次序的集 |
PriorityQueue | 允许高效删除最小元素的集合 |
HashMap | 存储键值关联的数据结构 |
TreeMap | 键值有序排列的映射表 |
EnumMap | 键值属于枚举类型的映射表 |
LinkedHashMap | 可以记住键值项添加次序的映射表 |
WeakHashMap | 其值无用武之地后可以被垃圾回收的映射表 |
IdentityHashMap | 一种用 == 而不是equals比较键值的映射表 |
2.1 链表
在Java程序设计语言中,所有链表实际上都是双向链接的。
java.util.List<E> 1.2
ListIterator<E> listIterator() //列表迭代器
ListIterator<e> listIterator(int index)
void add(int i, E element)
void addAll(int i , Collection<? extends E> elements)
E remove(int i)
E get(int i )
E set(int i, E element)
int indexOf(Object element)//第一次出现的位置,没有则返回-1
int lastIndexOf(Object element)
java.util.ListIterator<E> 1.2
void add(E newElement)//当前位置前添加一个元素
void set(E newElement)
boolean hasPrevious()
E previous() //返回前一个对象
int nextIndex()//返回下一次调用next方法时将返回的元素索引
int previousIndex() //同上
java.util.LinkedList<E> 1.2
LinkedList()
LinkedList(Collection<? extends E> elements)
void addFirst(E element)
void addLast(E element)
E getFirst()
E getLast()
E removeFirst()
E removeLast()
2.2 数组列表
在需要动态数组时需要用到Vector,所有方法都是同步的,可以由两个线程安全地访问一个Vector对象。,但是由一个线程访问Vector,代码在同步操作上会耗费大量的时间。因此在不需要同步的时候使用ArrayList。
2.3 散列集
散列码通过调用hasCode方法,在Java中,散列表用链表数组实现。
HashSet<>()//构造一个空散列表
HashSet(Collection<? extends E>) elements)//构造一个散列集,并将集合中所有元素添加到这个散列集中。
HashSet<>(int initialCapacity) // 指定容量(桶数)
HashSet(int initialCapacity, float loadFactor) // 加上装填因子0.0-1.0,当数量超过装填因子,将会自动用双倍的桶数再散列。
2.4 树集
树集与散列集十分类似,但树集是一个有序集合,元素需要实现Comparable接口。
当前使用的是红黑树实现的。
java.util.TreeSet<E> 1.2
//实现了Iterable,Colleation,SortedSet,NavigableSet(1.6)接口
TreeSet()
TreeSet(Comparator<? super E> comparator) //构造一个空树集
TreeSet(Collection<? extends E> comparator)
TreeSet(SortedSet<E> s)
java.util.SortedSet<E> 1.2//接口
Comparator<? super E> comparator()//返回用于对元素进行排序的比较器
E first()
E last()
java.util.NavigableSet<E> 6//接口
E higher(E value)
E lower(E value) //返回大于value的最小元素或小于value的最大元素,如果没有则返回null
E ceiling(E value)
E floor(E value)///返回大于等于value的最小元素或小于等于value的最大元素,如果没有则返回null
E poolFirst()
E poolLast()//删除并返回这个集中的最大元素或最小元素,这个集为空时返回null
Iterator<E> DescendingIterator() //返回一个按照递减顺序遍历集中元素的迭代器。
2.5队列与双端队列
java.util.Queue<E> 5.0//接口
boolean add(E element)
boolean offer(E element)// 如果没有满,则将元素添加到对类尾部并返回true,否则第一个抛出异常,第二个返回false
E remove()
E poll()// 如果队列不空,删除并返回头部元素。如果是空的,第一个方法抛出异常,第二个返回null.
E element()
E peek()// 如果队列不空,返回头部元素。如果是空的,第一个方法抛出异常,第二个返回null.
java.util.Deque<E> 6 //接口
void addFirst(E element)
void addLast(E element)
boolean offerFirst(E element)
boolean offerLast(E element) // 将给定元素添加到双端队列的头部或尾部。如果满了,前两个方法抛出异常,后两个方法返回false
E removeFirst()
E removeLast()
E pollFirst()
E pollLast()// 如果队列不空,删除并返回头部或尾部元素。如果是空的,前两个方法抛出异常,后两个方法返回null
E getFirst()
E getLast()
E peekFirst()
E peekLast()// 如果队列不空,返回头部或尾部元素。如果是空的,前两个方法抛出异常,后两个方法返回null
java.util.ArrayDeque<E> 6
//类,实现Deque
2.6优先级队列
Java优先级队列使用的数据结构是堆。
java.util.PriorityQueue 5.0
//类,实现了Queue接口
PriorityQueue()
PriorityQueue(int initialCapacity)
PriorityQueue(int initialCapacity, Comparator<? super E> c)//构造一个优先级队列,并指定比较器
三、映射
Java类库为映射提供了两个通用的实现:HashMap和TreeMap。这两个类都实现了Map接口。散列映射对键进行散列,树映射对键进行排序。
3.1 基本映射操作
java.util.Map<K, V> 1.2 //接口
V get(Object key)//获取与键对应的值,返回对应的对象或空,键也可以为空
default V getORDefault(Object key, V defaultValue)//若没有对应对象,返回默认值
V put(K key, V value)//插入映射返回null,如果键存在,则取代旧的对象,并返回旧的对象值。键可以为null,但值不可以。
void putAll(Map<? extends K, ? extends V> entries)
boolean containsKey(Object key)//如果有这个键返回true
boolean containsValue(Object value)
default void forEach(BiConsumer<? super K, ? super V> action) 8//应对动作
scores.forEach((k, v) ->
System.out.println("key=" + k + ", value=" + v)); //访问所有条目
java.util.HashMap<K, V> 1.2 //类,实现Map
HashMap()
HashMap(int initialCapacity)
HashMap(int initialCapacity, float loadFactor)//装填因子
java.util.TreeMap<K, V> 1.2//类,实现Map
TreeMap()
TreeMap(Comparator<? super K> c)
TreeMap(Map<? extends K, ? extends V> entries)
TreeMap(SortMap<? extends K, ? extends V> entries)
java.util.SortedMap<K, V> 1.2
Comparator<? super K> comparator()//返回比较器
K firstKey()
K lastKey()
3.2 更新映射项
对于统计单词在文件中出现的频次
1. counts.put(word, counts.getOrDefault(word, 0) + 1);
2. counts.putIfAbsent(word, 0);
counts.put(word, counts.get(word) +1);
3. counts.merge(word, 1, Integer::sum);
java.util.Map<K,V) 1.2
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) 8
// 如果key与一个非null值v关联,将函数应用到v与value,将key与结果关联,或者如果结果为null,则删除这个键。
//否则将key与value关联,返回get(key)
default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) 8
//将函数应用到v与get(key),将key与结果关联,或者如果结果为null,则删除这个键。返回get(key)
default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) 8
//如果key与一个非null值v关联,将函数应用到v与value,将key与结果关联,或者如果结果为null,则删除这个键。返回get(key)
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) 8
//将函数应用到get(key),除非key与一个非null值关联。将key与结果关联,或者如果结果为null,则删除这个键。返回get(key)
default void replaceAll(K key, BiFunction<? super K, ? super V, ? extends V> mappingFunction) 8
//在所有映射项上应用函数。将键与非null结果关联,对于null结果,则将相应的键删除。
3.3 映射视图
有三种视图:键集、值集合(不是一个集,因为允许重复)、键/值对集。
Set<K> keySet() //不是HashSet 也不是TreeSet而是实现了Set接口的另外某个类
Collection<V> values()
Set<Map.Entry<K, V>> entrySet()
for(Map.Entry<String, Employee>entry : staff.entrySet()){
String = entry.getKey();
Employee v = entry.getValue();
v = entry.setValue(v);
//老版本访问所有映射条目最高效方法。
}
3.4 弱散列映射
WeakHashMap 当对键的唯一引用来自散列条目时,这一数据结构将于垃圾回收器协同工作一起删除键/值对。
3.5 链接散列集与映射
LinkedHashSet 和 LinkedHashMap类用来记住插入元素项的顺序。
3.6枚举集与映射
EnumSet是一个枚举类型元素集的高效实现。没有公共的构造器,可以使用静态工厂方法构造这个集。
3.7 标识散列映射
IdentityHashMap有特殊的作用,在这个类中,键的散列值不是用hashCode函数计算的,而是用System.idntityHashCode方法计算的。根据对象的内存地址,对象比较时,使用的是 ==。
四、视图与包装器
4.1 轻量级集合包装器
Arrays类的静态方法asList返回一个包装了普通Java数组的List包装器。返回的对象不是ArrayList。它是一个视图对象,只能调用get和set方法。改变数组大小的所有方法,都会抛出Unsupported OperationException异常。
4.2 子范围
List group2 = staff.subList(10, 20) //老规矩,含左不含右。父子列表指向统一内存空间,会互相影响
group2.clear()//会将staff中10-20清除
4.3 不可修改视图
Collections.unmodifiableCollection
//Collection很特殊,equals会调用Object类的equals,hasCode,synchronizedCollection与checkedCollection也是如此
Collections.unmodifiableList
Collections.unmodifiableSet
Collections.unmodifiableSortedSet
Collections.unmodifiableNavigableSet
Collections.unmodifiableMap
Collections.unmodifiableSortedMap
Collections.unmodifiableNavigableMap
4.4 同步视图
Collections.synchronziedMap
受查视图
受查视图可以探测到某些类型问题
Collections.checkedList
五、算法
泛型集合接口有一个很大的优点,即算法只需要实现一次。
1
java.util.Collections 1.2
min,max,copy,fill,addAll,replaceAll,indexOfSubList,lastIndexOfSubList,swap,reverse,rotate,frequency,disjoint
2 批操作
coll1.removeAll(coll2) //从coll1中删除coll2出现的所有元素
coll1.retainAll(coll2)从coll1中删除未在coll2出现的所有元素
集合与数组的转换
list = Arrays.asList(array)
Object[] values = staff.toArray();//对象数组
String[] values = staff.toArray(new String[0])
String[] values = staff.toArray(new String[staff.size()])//这种情况下不会创建新数组