第6章 - Java 集合
作者:vwFisher
时间:2019-09-04
GitHub代码:https://github.com/vwFisher/JavaBasicGuide
目录
- 1 Java集合类(集合框架)
1 Java集合类(集合框架)
1.1 集合类概述
对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定。就使用集合容器进行存储。Java语言的java.util包中提供了一些集合类,这些集合类又被称为容器(数组也是个容器)
集合类特点:主要是用来存储对象容器,长度是可变的,不可以存储基本数据类型值
与数组对比:集合长度可变,用来存放对象。而数组长度固定,用来存放基本类型的数据
常见的集合有List集合、Set集合、 Map集合、其中List与Set实现了Collection接口,来看看类结构图
集合结构图.png如图所示:
一、集合接口: 8个接口(短虚线表示), 表示不同集合类型, 是集合框架的基础
Iterator, ListIterator,
Collection, List, Set, Map
SortedSet, SortedMap
二、抽象类: 5个抽象类(长虚线表示), 对集合接口的部分实现, 可扩展为自定义集合类
AbstractCollection, AbstractList, AbstractSet,
AbstractMap、AbstractSequentialList
三、实现类: 13个实现类(实线表示), 对接口的具体实现
Vector, Stack, ArrayList, LinkedList
HashSet, TreeSet, LinkedHashSet
HashMap, LinkedHashMap, TreeMap, Hashtable, Properties
WeakHashMap, IdentityHashMap
四、接口详解
- Collection接口 是一组允许重复的对象
- Set接口 继承 Collection。但不允许重复。使用自己内部的一个排列机制
- List接口 继承 Collection。允许重复,以元素插人的次序来放置元素,不会重新排列
- Map接口 是一组成对的键-值对象。即所持有的是 key-value (键值对)。Map中不能有重复的key。拥有自己的内部排列机制
五、关于null对象
-
可以包括null:ArrayList、LinkedList、Verctor、HashSet、LinkedHashSet、HashMap、LinkedHashMap
-
不可以包括null:TreeSet、TreeMap、Hashtable(键和值)
六、集合的特点对比
1.接口对比
- Set子接口:无序,不允许重复。检索元素效率低, 删除和插入效率高, 插入和删除不会引起元素位置改变. <对应类有 HashSet, TreeSet>
- List子接口:有序,可以有重复元素。和数组类似, List可以动态增长, 查找元素效率高, 插入删除元素效率低, 因为会引起其他元素位置改变. <相应类有 ArrayList, LinkedList, Vector>
2.实例比较
- HashSet: 以哈希表的形式存放元素, 插入删除速度很快.
- TreeSet: 以二叉树的形式存放元素
- ArrayList: 动态数组
- LinkedList: 链表、队列、堆栈
- Vector是一种老的动态数组:是线程同步的, 效率很低, 一般不赞成使用
七、Java容器的线程安全与非线程安全?
1.谈谈哪些是线程安全的容器, 哪些非线程安全的容器.
- 线程安全:Vector、HashTable、StringBuffer
- 非线程安全:ArrayList、LinkedList、HashMap、TreeMap、StringBuilder
2.线程安全有什么好处, 有什么坏处
线程安全即在多线程操作同一个 Vector 或 HashTable 对象时不会有任何问题. 但是线程安全必须要使用很多 synchronized 关键字来同步控制, 所以必然会导致性能的降低. Java后续版本出才出现了众多非线程安全的容器
3.安全与性能如何取舍.
如果是多个线程操作同一个对象, 那么使用线程安全的Vector; 否则, 就使用效率更高的ArrayList
4.补充说明, 非线程安全 != 不安全.
有人在使用过程中有一个不正确的观点: 我的程序是多线程的, 不能使用ArrayList要使用Vector, 这样才安全. 非线程安全并不是多线程环境下就不能使用. 注意我上面有说到: 多线程操作同一个对象. 注意是同一个对象. 如果是每个线程中new一个ArrayList, 而这个ArrayList只在这一个线程中使用, 那么肯定是没问题的
1.2 Iterable、Iterator、ListIterator
1.2.1 Iterable
一个集合对象要表明自己支持迭代,能有使用foreach语句的特权,就必须实现Iterable接口,表明是可迭代的!然而实现Iterable接口,就必需为foreach语句提供一个迭代器。来看看接口定义内容
public interface Iterable<T> {
Iterator<T> iterator(); // 返回迭代器Iterator
default void forEach(Consumer<? super T> action) { // 提供forEach语法糖
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() { // 创建并返回一个可分割迭代器
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
1.2.2 Iterator - 迭代器
Iterator就是迭代器,规定迭代接口定义。
public interface Iterator<E> {
boolean hasNext(); // 如果仍有元素可以迭代, 则返回true
E next(); // 返回迭代的下一个元素
// 从迭代器指向的collection中移除迭代器返回的最后一个元素(可选操作),由子类定义,默认不支持
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
1.2.3 ListIterator
ListIterator也是接口,是对Iterator的接口定义的扩展
public interface ListIterator<E> extends Iterator<E> {
boolean hasNext();
E next();
boolean hasPrevious();
E previous();
int previousIndex();
void remove();
void set(E e);
void add(E e);
}
1.3 Collection - 单列集合
Collection(单列集合):一次添加一个元素<T>。它是一个接口,定义了单列集合接口约束。是单列集合的顶层定义,List与Set接口都实现Collection,接口定义如下:
Collection实现Iterable接口,即包含提供迭代器方法,也包括forEach语法糖遍历方法。
添加:
boolean add(E e); // 添加一个元素
boolean addAll(Collection<? extends E> c); // 添加元素集合
删除:
boolean remove(Object o); // 删除一个元素
boolean removeAll(Collection<?> c); // 删除元素集合
void clear(); // 清空
判断:
boolean contains(Object o); // 判断是否包含一个元素
boolean containsAll(Collection<?> c); // 判断是否包含元素集合
boolean isEmpty(); // 判断集合是否有元素
boolean equals(Object o); // 判断与指定对象,比较方式由子类实现,一般与haseCode函数相关
获取
int hashCode(); // 获取该集合对象的hashCode
int size(); // 获取该集合元素的大小(数量)
Iterator<E> iterator(); // 获取迭代器对象
boolean retainAll(Collection<?> c); // 与元素集合C,取交集
转化数组:
Object[] toArray(); // 将集合转成Object数组
<T> T[] toArray(T[] a); // 将集合转成自定义对象数组
default方法:
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
@Override
default Spliterator<E> spliterator() { // 创建并返回一个可分割迭代器
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() { // 转化成Stream对象
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() { // 转化成并行Stream对象
return StreamSupport.stream(spliterator(), true);
}
AbstractCollection是实现Collection的抽象类,通过结合Iterator接口约束,对一些方法的实现。
1.3.1 List - 列表
AbstractList是实现List的抽象类,通过结合ListIterator接口约束,对一些方法的实现。
List特点: 有序(存入和取出的顺序一致), 元素都有索引(角标), 元素可以重复
List:(是有序的)
|-- ArrayList:内部是数组数据结构, 是不同步的. 替代了Vector. 查询的速度快.
|-- LinkedList:内部是链表数据结构, 是不同步的. 增删元素的速度很快.
|-- Vector:内部是数组数据结构, 是同步的. 增删, 查询都很慢
List接口继承了Collection接口,在Collection基础上,扩展定义列表的接口规范。扩展定义的方法:
void add(int index, E element); // 在索引位置插入元素(索引从0开始)
boolean addAll(int index, Collection<? extends E> c); // 在指定索引位置插入元素集合
E set(int index, E element); // 指定元素替换列表中指定索引位置的元素, 返回被替换的元素
E remove(int index); // 移除指定索引位置的元素, 返回被移除的元素
E get(int index); // 用于获取指定索引位置的元素
int indexOf(Object o); // 返回列表中对象最后一次出现的索引位置, 如果集合中不包含该元素, 则返回-1
int lastIndexOf(Object o); // 返回列表中对象最后一次出现的索引位置, 如果集合中不包含该元素, 则返回-1
ListIterator<E> listIterator(); // 用来获取一个包含所有对象的ListIterator列表迭代器
ListIterator<E> listIterator(int index);
List<E> subList(int fromIndex, int toIndex); // 获取子集合列表,从fromIndex -> toIndex
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
1.3.1.1 ArrayList类
(basic.coll.collection.list.ArrayListDemo)
- 底层数据结构:Object对象类型的数组,允许所有元素,包括null
- 优点:可以根据索引位置对集合进行快速的随机访问
- 缺点:向指定的索引位置插入对象或删除对象的速度较慢
- 使用场景:读 多于 写的场景
- 扩容机制:正常情况下会扩容1.5倍,特殊情况下(新扩展数组大小已经达到了最大值)则只取最大值。
- 扩容时机:调用add()方法的重载时,第一步是检查容量,如果容量不够则进行扩容
类定义:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
继承了AbstractList、实现List接口、支持随机访问、拷贝、序列化
重要的类属性:
private static final int DEFAULT_CAPACITY = 10; // 缺省容量
private static final Object[] EMPTY_ELEMENTDATA = {}; // 空对象数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 缺省空对象数组
transient Object[] elementData; // 元素数组(trabsuebt,该变量不包括在序列化的表示中)
private int size; // 实际元素大小,默认为0
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 最大数组容量
构造函数:
public ArrayList(int initialCapacity)
public ArrayList()
public ArrayList(Collection<? extends E> c)
核心函数实现分析 add():
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 取保数组又合适的大小
elementData[size++] = e;
return true;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 修改次数的记录:修改加1
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; // 旧容量
int newCapacity = oldCapacity + (oldCapacity >> 1); // 1.5倍扩容
if (newCapacity - minCapacity < 0) // 新容量小于参数指定容量,修改新容量
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) // 新容量大于最大容量
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); // 拷贝扩容
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
正常情况下会扩容1.5倍,特殊情况下(新扩展数组大小已经达到了最大值)则只取最大值。modCount意思是修改次数,在集合几个容器中基本上都有。
其他需要说明的,indexOf()、set()、get()、remove()函数实现,第一步一般都是检查索引是否合法。remove移除指定下标的元素,此时会把指定下标到数组末尾的元素向前移动一个单位,并且会把数组最后一个元素设置为null,这样是为了方便之后将整个数组不被使用时,会被GC
1.3.1.2 LinkedList类
(basic.coll.collection.list.LInkedListDemo)
- 底层数据结构:采用Node对象,双向链表结构,有一个头结点和一个尾结点(JDK1.6之前为循环链表,JDK1.7取消了循环)
- 优点:插入、删除效率比较高。
- 缺点:对于随机访问集合中的对象, 效率较慢
- 使用场景:写 多于 读的场景。也可以拿来实现堆栈和队列
类定义:
public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
与ArrayList不同的,主要在于AbstractSequentialListh和Deque。Deque定义双向队列的接口方法。
类的属性
transient int size = 0; // 容量
transient Node<E> first; // 首节点
transient Node<E> last; // 尾节点
private static class Node<E> { // Node节点的定义
E item; // 当前元素
Node<E> next; // 前一个节点指针
Node<E> prev; // 后一个节点指针
}
说明:LinkedList的属性非常简单,一个头结点、一个尾结点、一个表示链表中实际元素个数的变量。都有transient关键字修饰,这也意味着在序列化时该域是不会序列化的。
构造函数:
public LinkedList()
public LinkedList(Collection<? extends E> c)
实现的Deque方法说明:
void addFirst(E e) 将指定元素插入此列表的开头
void addLast(E e) 将指定元素添加到此列表的结尾
boolean offer(E e) 将指定元素添加到此列表的末尾(最后一个元素)
boolean offerFirst(E e) 在此列表的开头插入指定的元素
boolean offerLast(E e) 在此列表末尾插入指定的元素
void push(E e) 将元素推入此列表所表示的堆栈
E element() 获取但不移除此列表的头(第一个元素)
E getFirst() 返回此列表的第一个元素
E getLast() 返回此列表的最后一个元素
E peek() 获取但不移除此列表的头(第一个元素)
E peekFirst() 获取但不移除此列表的第一个元素; 如果此列表为空, 则返回 null
E peekLast() 获取但不移除此列表的最后一个元素; 如果此列表为空, 则返回 null
E poll() 获取并移除此列表的头(第一个元素)
E pollFirst() 获取并移除此列表的第一个元素; 如果此列表为空, 则返回 null
E pollLast() 获取并移除此列表的最后一个元素; 如果此列表为空, 则返回 null
E pop() 从此列表所表示的堆栈处弹出一个元素
E remove() 获取并移除此列表的头(第一个元素)
E removeFirst() 移除并返回此列表的第一个元素
boolean removeFirstOccurrence(Object o) 从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)
E removeLast() 移除并返回此列表的最后一个元素
boolean removeLastOccurrence(Object o) 从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)
Iterator<E> descendingIterator() 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器
核心函数实现分析 addAll():
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
addAll会把集合先转化为数组。考虑的是2点:
- 传入的集合是对象(引用),转化数组toArray,可以避免过程中,该集合对象被修改
- 转化成数组遍历,比在集合中遍历速度要快,因为集合需要转化成迭代器来遍历
1.3.1.2 Vector类
(示例: basic.coll.collection.list.VectorDemo)
底层实现与ArrayList结构类似,操作方法大同小异,不同点在于:
- Vector的方法都是用了synchronized,即线程安全的列表容器
- 扩容,ArrayList是1.5倍扩容,而Vector有个属性capacityIncrement定义扩容数量,如果没有定义默就是2倍扩容
对于Vector的子类Stack,Stack栈的特点:先进后出,主要实现了一下几个方法
1.3.1.4 ArrayList和LinkedList的区别
ArrayList:通过数组来实现的,读取性能很高,随机访问时间复杂度为O(1),适用于读大于写的场景
LinkedList:通过双向队列来实现的,更新效率更高,写只需要修改前后两个节点的相关引用,但是读取效率比较低,需要最多遍历一半长度的队列,适用与写大于读的场景
public E push(E item) // 向栈顶(数组末端)放入元素
public synchronized E pop() // 弹出栈顶,移除数组末端元素,并放回
public synchronized E peek() // 获取栈顶元素(数组末端元素)返回,不会移除
1.3.1.5 RandomAccess接口
查看源码我们发现实际上 RandomAccess 接口中什么都没有定义。所以,在我看来 RandomAccess 接口不过是一个标识罢了。标识什么? 标识实现这个接口的类具有随机访问功能。
在 binarySearch()方法中,它要判断传入的list 是否 RamdomAccess 的实例,如果是,调用indexedBinarySearch()方法,如果不是,那么调用iteratorBinarySearch()方法
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
ArrayList 实现了 RandomAccess 接口, 而 LinkedList 没有实现。为什么呢?还是和底层数据结构有关!ArrayList 底层是数组,而 LinkedList 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。,ArrayList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能。 RandomAccess 接口只是标识,并不是说 ArrayList 实现 RandomAccess 接口才具有快速随机访问功能的!
对于 list 的遍历方式选择:
- 实现了 RandomAccess 接口的list,优先选择普通 for 循环 ,其次 foreach,
- 未实现 RandomAccess接口的list,优先选择iterator遍历(foreach遍历底层也是通过iterator实现的,),大size的数据,千万不要使用普通for循环
1.3.2 Set接口的常用方法
Set接口继承了Collection接口,在Collection基础上,扩展定义Set的接口规范。扩展定义的方法:
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
void clear();
int hashCode();
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
AbstractSet 是实现 Set 的抽象类,通过结合 Iterator 接口约束,对一些方法的实现。
Set:元素不可以重复, 是无序
|-- HashSet:内部数据结构是哈希表 , 是不同步的.
|-- LinkedHashSet:
|-- TreeSet:可以对Set集合中的元素进行排序. 是不同步的.
由于Set集合中不允许存在重复值, 因此可以使用Set集合中的addAll()方法, 将Collection集合添加到Set集合中并除掉重复值
由于Set集合中的对象时无序的, 遍历Set结合的结果与插入Set集合的顺序并不相同
一、如何保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的.
- 如果对象的hashCode值不同, 那么不用判断equals方法, 就直接存储到哈希表中.
- 如果对象的hashCode值相同, 那么要再次判断对象的equals方法是否为true. 如果为true, 视为相同元素, 不存. 如果为false, 那么视为不同元素, 就进行存储.
记住: 如果元素要存储到HashSet集合中, 必须覆盖hashCode方法和equals方法.
一般情况下, 如果定义的类会产生很多对象, 比如人, 学生, 书, 通常都需要覆盖equals, hashCode方法.
二、建立对象判断是否相同的依据
if (this.hashCode() == obj.hashCode() && this.equals(obj))
三、哈希表确定元素是否相同
- 判断的是两个元素的哈希值是否相同。如果相同,在判断两个对象的内容是否相同。
- 判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。如果哈希值不同,就不需要判断equals
四、判断元素唯一性的方式
就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
五、TreeSet对元素进行排序的 两种方式
- 让元素自身具备比较功能,元就需要实现Comparable接口,覆盖compareTo方法。如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?
- 让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。
1.3.2.1 HashSet类
(示例: basic.coll.collection.set.HashSetDemo)
底层数据结构:采用HashMap的键,来作为对象的存储容器,允许null。因为Map的key不能重复,所以自然Set就不允许存在重复的元素。所以存储元素的时候, 使用的元素的hashCode方法来确定位置, 如果位置相同, 在通过元素的equals来确定是否相同。
1.3.2.2 LinkedHashSet类(HashSet的子类)
(示例: basic.coll.collection.set.LinkedHashSetDemo)
底层数据结构: 与HashSet类似,除了底层数据结构是采用LinkedHashMap。所以是有序的
1.3.2.3 TreeSet类
(示例: basic.coll.collection.set.TreeSetDemo)
- 底层实现: 红黑树(自平衡的排序二叉树)。底层基于TreeMap的NavigableSet保存数据, 其中对象作为map的key, 所以不允许存在重复的键, 所以Set不可重复. HashSet集合数据结构是哈希表, 所以存储元素的时候, 使用的元素的hashCode方法来确定位置, 如果位置相同, 在通过元素的equals来确定是否相同。允许null
- 优点: 删除和插入效率高
- 缺点: 检索元素效率低
- 语法: TreeSet<Object> list = new TreeSet<Object>();
方法(只列出基于Set扩展的):
构造
TreeSet() 构造一个新的空set, 该set根据其元素的自然顺序进行排序
TreeSet(NavigableMap<E,Object> m)
TreeSet(Comparator<? super E> comparator) 构造一个新的空TreeSet, 它根据指定比较器进行排序
TreeSet(Collection<? extends E> c) 构造一个包含指定collection元素的新 TreeSet, 它按照其元素的自然顺序进行排序
TreeSet(SortedSet<E> s) 构造一个与指定有序set具有相同映射关系和相同排序的新TreeSet
获取
Iterator<E> descendingIterator() 返回在此set元素上按降序进行迭代的迭代器
NavigableSet<E> descendingSet() 返回此set中所包含元素的逆序视图
NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) 返回此set的部分视图, 其元素范围从fromElement到toElement
NavigableSet<E> headSet(E toElement, boolean inclusive) 返回此set的部分视图, 其元素小于(或等于, 如果inclusive为true)toElement
NavigableSet<E> tailSet(E fromElement, boolean inclusive) 返回此set的部分视图, 其元素大于(或等于, 如果inclusive为true)fromElement
SortedSet<E> subSet(E fromElement, E toElement) 返回此set的部分视图, 其元素从fromElement(包括)到toElement(不包括)
SortedSet<E> headSet(E toElement) 返回此set的部分视图, 其元素严格小于toElement
SortedSet<E> tailSet(E fromElement) 返回此set的部分视图, 其元素大于等于fromElement
Comparator<? super E> comparator() 返回对此set中的元素进行排序的比较器; 如果此set使用其元素的自然顺序, 则返回null
E first() 返回此set中当前第一个(最低)元素
E last() 返回此set中当前最后一个(最高)元素
E lower(E e) 返回此set中严格小于给定元素的最大元素; 如果不存在这样的元素, 则返回 null
E floor(E e) 返回此 set 中小于等于给定元素的最大元素; 如果不存在这样的元素, 则返回 null
E ceiling(E e) 返回此 set 中大于等于给定元素的最小元素; 如果不存在这样的元素, 则返回 null
E higher(E e) 返回此 set 中严格大于给定元素的最小元素; 如果不存在这样的元素, 则返回 null
E pollFirst() 获取并移除第一个(最低)元素; 如果此set为空, 则返回null
E pollLast() 获取并移除最后一个(最高)元素; 如果此set为空, 则返回 null
Object clone() 返回TreeSet实例的浅表副本, 浅克隆
1.3.3 Collection泛型
JDK1.5 出现的安全机制, 不用 <>
就是 Object 类型
一、好处:
- 将运行时期的问题ClassCastException转到了编译时期(编写代码时期)
- 避免了强制转换的麻烦
二、泛型<>
什么时候用?(泛型类同理)
当操作的引用数据类型不确定的时候,就使用<>
。将要操作的引用数据类型传入即可,其实<>
就是一个用于接收具体引用数据类型的参数范围
注意在程序中,只要用到了带有<>
的类或者接口,就要明确传入的具体引用数据类型
泛型技术是给编译器使用的技术,用于编译时期。确保了类型的安全。运行时。会将泛型去掉,生成的 class 文件中是不带泛型的,这个称为泛型的擦除,为了兼容运行的类加载器,所以擦除
泛型的补偿:在运行时,通过获取元素的类型进行转换动作,不用使用者再强制转换了
三、泛型的通配符: ?
未知类型(定义泛型函数时候)
-
? extends E
:接收E类型或者E的子类型对象(上限). 一般存储对象的时候用. 比如 添加元素 addAll -
? super E
:接收E类型或者E的父类型对象(下限). 一般取出对象的时候用. 比如 比较器
1.3.3.4 使用Collection技巧
需要唯一吗?
|-- 需要: set
|-- 需要制定顺序吗?
|-- 需要: TreeSet
|-- 不需要: HashSet, 但是想要一个和存储一致的顺序(有序) : LinkedHashSet
|-- 不需要: List
|-- 需要频繁增删吗?
|-- 需要: LinkedList
|-- 不需要: ArrayList
- 前缀名: 集合的数据结构: Array、Linked、Hash、Tree
- 后缀名: 集合所属的体系: List、Set
一、记忆方法
- array: 数组;查询快,有角标
- linked: 链表;增删快,add、get、remove + first last 方法
- hash: 哈希表;唯一性,元素需要覆盖 hashcode 方法和 equals 方法
- tree: 二叉树;排序,两个接口: Comparable、Comparator
而且通常这些常用的集合容器都是不同步的
二、显示数据的2种方式
1).迭代器: Iterator(3个方法) [Collection子类用的]
Iterator<String> lts = s.iterator();
while (lts.hasNext()) {
System.out.println(lts.next());
}
2).枚举: Enumeration(2个方法) [Vector使用的]
1).boolean hasMoreElements()
2).Object nextElement()
Enumeration<String> en = v.elements();
while(en.hasMoreElements()){
System.out.println("en.nextElement(): " + en.nextElement());
}
3).Iterator 和 Enumeration 的区别
Iterator 是用来替代 Enumeration 的,Enumeration 中只定义了两个方法,不具备删除功能。
4).调用 next() 方法后才可以调用 remove() 方法
而且每次调用 next() 后最多只能调用一次 remove() 方法,否则抛出IllegalStateException异常。
1.4 Map - 双列集合
Map一次添加一对元素<K,V>
,存储的是键值对,保证键的唯一性。Map接口提供了将键映射到值得对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。Map是双列集合的顶层定义,HashMap与TreeMap都实现Map
Map常用的子类
|-- Hashtable:内部结构是哈希表, 是同步的. 不允许null作为键, null作为值.
|-- Properties:用来存储键值对型的配置文件的信息, 可以和IO技术相结合.
|-- HashMap:内部结构是哈希表, 不是同步的. 允许null作为键, null作为值. 无序
|-- LinkedHashMap:有序哈希Map
|-- TreeMap:内部结构是二叉树, 不是同步的. 可以对Map集合中的键进行排序.
接口定义如下:
添加:
V put(K key, V value) 向集合中添加指定的key与value的映射关系
void putAll(Map<? extends K, ? extends V> m) 添加一个map集合进去
删除:
V remove(Object key) 根据指定的key删除这个键值对
boolean remove(Object key, Object value) JDK1.8, 子类实现
void clear() 清空map集合
判断:
boolean containsKey(Object key) 如果此映射包含指定键的映射关系, 则返回true
boolean containsValue(Object value) 如果此映射将一个或多个键映射到指定值, 则返回true
boolean equals(Object o) 比较的是元素是否相同
boolean isEmpty() 判断集合是否有元素
获取:
int size() 获取键值对的个数
V get(Object key) 如果存在指定的键对象, 则返回该对象对应的值, 否则返回null
default V getOrDefault(Object key, V defaultValue)
Set<K> keySet() 返回该集合中的所有键对象组成的Set集合
Collection<V> values() 返回该集合中所有值对象形成的Collection集合
Set<Map.Entry<K, V>> entrySet()
default void forEach(BiConsumer<? super K, ? super V> action)
JDK1.8:子类实现
default V replace(K key, V value)
default boolean replace(K key, V oldValue, V newValue)
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
default V putIfAbsent(K key, V value)
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
Map的内部接口Entry定义:
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getKey().compareTo(c2.getKey());
}
public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> c1.getValue().compareTo(c2.getValue());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
}
public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
Objects.requireNonNull(cmp);
return (Comparator<Map.Entry<K, V>> & Serializable) (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
}
}
1.4.1 Map接口的实现类
Map 接口常用的实现类有 HashMap 和 TreeMap,通常建议使用 HashMap 实现类实现 Map 集合,因为由 HashMap 类实现的 Map 集合对于添加和删除映射关系效率更高。
HashMap 是基于哈希表的Map接口的实现,HashMap 通过哈希吗对其内部的映射关系进行快速查找。由 HashMap 类实现的 Map 集合对于添加或删除映射关系效率较高。而 TreeMap 中的映射关系存在一定的顺序,如果希望 Map 集合中的对象存在一定的顺序,应该使用 TreeMap 类实现 Map 集合。
1.4.1.1 HashMap类
(basic.coll.map.HashMapDemo)
该类基于哈希表的Map接口的实现,此实现提供所有可选的映射操作,并允许使用 null值 和 null键,但必须保证键的唯一性。 HashMap通过哈希对其内部的映射关系进行快速查找,此类不保证映射的顺序,特别是不保证该顺序恒久不变(无序)。
-
底层实现: Node<K, V> implements Map.Entry<K,V> 内置对象实现(链表) + 数组的方式。JDK1.8 之前 HashMap 由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的(
拉链法
解决冲突)。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间 - 语法: HashMap<K, V> list = new HashMap<K, V>()
方法(只列出基于Map扩展的,JDK1.8方法均由该类实现):
构造
HashMap() 构造一个具有默认初始容量(16)和默认加载因子(0.75)的空HashMap
HashMap(int initialCapacity) 构造一个带指定初始容量和默认加载因子(0.75)的空HashMap
HashMap(int initialCapacity, float loadFactor) 构造一个带指定初始容量和加载因子的空HashMap
HashMap(Map<? extends K, ? extends V> m) 构造一个映射关系与指定Map相同的新HashMap
获取
V getOrDefault(Object key, V defaultValue) JDK1.8
void forEach(BiConsumer<? super K, ? super V> action) JDK1.8
删除
boolean remove(Object key, Object value) JDK1.8
JDK1.8 V replace(K key, V value)
boolean replace(K key, V oldValue, V newValue)
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
V putIfAbsent(K key, V value)
V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
克隆
Object clone() 浅克隆
1.4.1.2 TreeMap类
(basic.coll.map.TreeMapDemo)
- 底层实现:红黑树(自平衡的排序二叉树)
该类不仅实现了Map接口,还实现了 java.util.SortedMap 接口。因此集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系上,TreeMap类比HashMap性能差一点。
由于 TreeMap 类实现的 Map集合 中的映射关系是根据键对象按照一定的顺序(字典排序)排列的,因此 不允许键对象 是 null
可以通过HashMap类创建Map集合,当需要顺序输出时,再创建一个完成相同映射关系的TreeMap类实例
方法(只列出基于Map扩展的,JDK1.8方法均由该类实现):
构造
TreeMap () 使用键的自然顺序构造一个新的、空的树映射
TreeMap(Comparator<? super K> comparator) 构造一个新的、空的树映射, 该映射根据给定比较器进行排序
TreeMap(Map<? extends K, ? extends V> m) 构造一个与给定映射具有相同映射关系的新的树映射, 该映射根据其键的自然顺序进行排序
TreeMap(SortedMap<K, ? extends V> m) 构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射
获取
Map.Entry<K,V> firstEntry() 返回一个与此映射中的最小键关联的键-值映射关系; 如果映射为空, 则返回null
K firstKey() 返回此映射中当前第一个(最低)键
Map.Entry<K,V> lastEntry() 返回与此映射中的最大键关联的键-值映射关系; 如果映射为空, 则返回null
K lastKey() 返回映射中当前最后一个(最高)键
Map.Entry<K,V> pollFirstEntry() 移除并返回与此映射中的最小键关联的键-值映射关系; 如果映射为空, 则返回null
Map.Entry<K,V> pollLastEntry() 移除并返回与此映射中的最大键关联的键-值映射关系; 如果映射为空, 则返回null
Map.Entry<K,V> floorEntry(K key) 返回一个键-值映射关系, 它与小于等于给定键的最大键关联; 如果不存在这样的键, 则返回 null
K floorKey(K key) 返回小于等于给定键的最大键; 如果不存在这样的键, 则返回null
Map.Entry<K,V> ceilingEntry(K key) 返回一个键-值映射关系, 它与大于等于给定键的最小键关联; 如果不存在这样的键, 则返回 null
K ceilingKey(K key) 返回大于等于给定键的最小键; 如果不存在这样的键, 则返回null
Map.Entry<K,V> higherEntry(K key) 返回一个键-值映射关系, 它与严格大于给定键的最小键关联; 如果不存在这样的键, 则返回null
K higherKey(K key) 返回严格大于给定键的最小键; 如果不存在这样的键, 则返回null
Map.Entry<K,V> lowerEntry(K key) 返回一个键-值映射关系, 它与严格小于给定键的最大键关联; 如果不存在这样的键, 则返回null
K lowerKey(K key) 返回严格小于给定键的最大键; 如果不存在这样的键, 则返回nul
Comparator<? super K> comparator() 返回对此映射中的键进行排序的比较器; 如果此映射使用键的自然顺序, 则返回null
NavigableSet<K> navigableKeySet() 返回此映射中所包含键的NavigableSet视图
NavigableSet<K> descendingKeySet() 返回此映射中所包含键的逆序NavigableSet视图
NavigableMap<K, V> descendingMap() 返回此映射中所包含映射关系的逆序视图
SortedMap<K,V> headMap(K toKey) 返回此映射的部分视图, 其键值严格小于toKey
NavigableMap<K,V> headMap(K toKey, boolean inclusive) 返回此映射的部分视图, 其键小于(或等于, 如果inclusive为true)toKey
SortedMap<K,V> tailMap(K fromKey) 返回此映射的部分视图, 其键大于等于fromKey
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) 返回此映射的部分视图, 其键大于(或等于, 如果inclusive为true)fromKey
SortedMap<K,V> subMap(K fromKey, K toKey) 返回此映射的部分视图, 其键值的范围从fromKey(包括)到toKey(不包括)
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) 返回此映射的部分视图, 其键的范围从fromKey到toKey
void forEach(BiConsumer<? super K, ? super V> action) JDK1.8
JDK1.8
V replace(K key, V value)
boolean replace(K key, V oldValue, V newValue)
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
克隆
Object clone() 返回此TreeMap实例的浅表副本, 浅克隆
1.4.1.3 Hashtable类
(basic.coll.map.HashtableDemo)
此类实现一个哈希表,该哈希表将键映射到相应的值。任何 非null对象 都可以用作键或值。为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。所有方法均加了 synchronized(即同步)
- 底层实现: Node<K, V> implements Map.Entry<K,V> 内置对象实现(链表) + 数组的方式
方法(只列出基于Map扩展的,JDK1.8方法均由该类实现):
构造
Hashtable() 用默认的初始容量(11)和加载因子(0.75)构造一个新的空哈希表
Hashtable(int initialCapacity) 用指定初始容量和默认的加载因子(0.75)构造一个新的空哈希表
Hashtable(int initialCapacity, float loadFactor) 用指定初始容量和指定加载因子构造一个新的空哈希表
Hashtable(Map<? extends K, ? extends V> t) 构造一个与给定的Map具有相同映射关系的新哈希表
获取
synchronized Enumeration<K> keys() 返回此哈希表中的键的枚举
synchronized Enumeration<V> elements() 返回此哈希表中的值的枚举
synchronized Object clone() 创建此哈希表的浅表副本, 浅克隆
synchronized String toString() 返回此Hashtable对象的字符串表示形式, 其形式为ASCII字符","(逗号加空格)分隔开的、括在括号中的一组条目
synchronized boolean equals(Object o) 按照Map接口的定义, 比较指定Object与此Map是否相等
synchronized int hashCode() 按照Map接口的定义, 返回此Map的哈希码值
JDK1.8 synchronized V getOrDefault(Object key, V defaultValue)
synchronized void forEach(BiConsumer<? super K, ? super V> action)
synchronized void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
synchronized V putIfAbsent(K key, V value)
synchronized boolean remove(Object key, Object value)
synchronized boolean replace(K key, V oldValue, V newValue)
synchronized V replace(K key, V value)
synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
synchronized V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
synchronized V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
synchronized V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
1.4.1.4 Properties(Hashtable子类)
(basic.coll.map.PropertiesDemo)
Properties类表示了一个持久的属性集。Properties可保存在流中或从流中加载
特点:
- 该集合中的键和值都是字符串类型
- 集合中的数据可以保存到流中,或从流中获取
通过该集合用于操作以键值对形式存在配置文件
构造
Properties() 创建一个无默认值的空属性列表
Properties(Properties defaults) 创建一个带有指定默认值的空属性列表
操作
String getProperty(String key) 用指定的键在此属性列表中搜索属性
String getProperty(String key, String defaultValue) 用指定的键在属性列表中搜索属性
synchronized Object setProperty(String key, String value) 调用 Hashtable 的方法 put
获取
Enumeration<?> propertyNames() 返回属性列表中所有键的枚举, 如果在主属性列表中未找到同名的键, 则包括默认属性列表中不同的键
Set<String> stringPropertyNames() 返回此属性列表中的键集, 其中该键及其对应值是字符串, 如果在主属性列表中未找到同名的键, 则还包括默认属性列表中不同的键
其他
synchronized void load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)
synchronized void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)
void save(OutputStream out, String comments) 已过时, 如果在保存属性列表时发生I/O错误, 则此方法不抛出IOException. 保存属性列表的首选方法是通过store(OutputStream out, String comments)方法或storeToXML(OutputStream os, String comment)方法来进行
void store(Writer writer, String comments) 以适合使用load(Reader)方法的格式, 将此Properties表中的属性列表(键和元素对)写入输出字符
void store(OutputStream out, String comments) 以适合使用load(InputStream)方法加载到Properties表中的格式, 将此Properties表中的属性列表(键和元素对)写入输出流
synchronized void loadFromXML(InputStream in) 将指定输入流中由XML文档所表示的所有属性加载到此属性表中
void storeToXML(OutputStream os, String comment) 发出一个表示此表中包含的所有属性的XML文档
void storeToXML(OutputStream os, String comment, String encoding) 使用指定的编码发出一个表示此表中包含的所有属性的XML文档
void list(PrintStream out) 将属性列表输出到指定的输出流
void list(PrintWriter out) 将属性列表输出到指定的输出流
因为Properties继承于 Hashtable,所以可以对 Properties 对象应用 put 和 putAll 方法。不建议使用这两个方法,因为它们允许调用者插入其键或值不是 String 的项,相反应该使用 setProperty 方法。如果在不安全
的 Properties 对象(即包含 非String 的键或值)上调用 store 或 save 方法,则该调用将失败
类似地,如果在不安全
的 Properties 对象(即包含 非String 的键)上调用 propertyNames 或 list 方法,则该调用将失败
load(Reader) / store(Writer, String)方法按下面所指定的、简单的面向行的格式在基于字符的流中加载和存储属性. 除了输入/输出流使用ISO 8859-1字符编码外,load(InputStream) / store(OutputStream, String) 方法与 load(Reader) / store(Writer, String) 对的工作方式完全相同。可以使用 Unicode 转义来编写此编码中无法直接表示的字符;转义序列中只允许单个'u'字符。可使用 native2ascii 工具对属性文件和其他字符编码进行相互转换
loadFromXML(InputStream) 和 storeToXML(OutputStream, String, String) 方法按简单的 XML 格式加载和存储属性。默认使用 UTF-8 字符编码,但如果需要,可以指定某种特定的编码。XML 属性文档具有以下DOCTYPE声明:
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
1.4.1.5 LinkedHashMap(HashMap子类)
(basic.coll.map.LinkedHashMapDemo)
- 底层实现: LinkedHashMap 继承自 HashMa,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外 LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。同时通过对链表进行相应的操作,实现了访问顺序相关逻辑。
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于:该类维护着一个运行于所有条目的双重链接列表,是有序的 HashMap
方法(只列出基于Map扩展的,JDK1.8方法均由该类实现):
构造
LinkedHashMap() 构造一个带默认初始容量(16)和加载因子(0.75)的空插入顺序LinkedHashMap实例
LinkedHashMap(int initialCapacity) 构造一个带指定初始容量和默认加载因子(0.75)的空插入顺序LinkedHashMap实例
LinkedHashMap(int initialCapacity, float loadFactor) 构造一个带指定初始容量和加载因子的空插入顺序LinkedHashMap实例
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 构造一个映射关系与指定映射相同的插入顺序LinkedHashMap实例
LinkedHashMap(Map<? extends K, ? extends V> m) 构造一个带指定初始容量、加载因子和排序模式的空LinkedHashMap实例
1.4.2 遍历Map数据总结
一、Collection方法,只遍历value
Collection<String> values = m1.values();
Iterator<String> it1 = values.iterator();
while (it1.hasNext()) {
System.out.println(it1.next());
}
二、keySet方法(取出map中的所有元素)
原理:通过 keySet() 获取 Map 中所有的键所在的 Set 集合,再通过 Set 的迭代器获取到每一个键,再对每一个键通过 Map 集合的 get(String key) 获取其对应的值即可。
Set<Integer> keySet = m1.keySet();
Iterator<Integer> its = keySet.iterator();
while (its.hasNext()) {
Integer key = its.next();
String value = m1.get(key);
System.out.print("{key=" + key + ", value=" + value + "},");
}
三、entrySet方法,效率最高
通过 Map 转成 Set 就可以迭代。找到了另一个方法 entrySet()。该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是 Map.Entry 类型
Set<Map.Entry<Integer, String>> entrySet = m1.entrySet();
Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.print("{key=" + key + ", value=" + value + "},");
}
四、JDK1.8 新特性,forEach方法
m1.forEach((key, value) -> {
System.out.print("{key=" + key + ", value=" + value + "},");
});
1.3 Collections(集合框架工具类)
(basic.coll.CollectionsDemo)
此类完全由在 collection 上进行操作或返回 collection 的静态方法组成。它包含在collection上操作的多态算法,即包装器
,包装器返回由指定 collection 支持的 新collection,以及少数其他内容
方法(均为static静态方法) 说明
<T extends Comparable<? super T>> void sort(List<T> list)
根据元素的自然顺序, 对指定列表按升序进行排序
<T> void sort(List<T> list, Comparator<? super T> c)
根据指定比较器产生的顺序对指定列表进行排序
<T> int binarySearch(List<? extends Comparable<? super T>> list, T key)
使用二分搜索法搜索指定列表, 以获得指定对象
<T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
使用二分搜索法搜索指定列表, 以获得指定对象
void reverse(List<?> list) 反转指定列表中元素的顺序
void shuffle(List<?> list) 使用默认随机源对指定列表进行置换
void shuffle(List<?> list, Random rnd) 使用指定的随机源对指定列表进行置换
void swap(List<?> list, int i, int j) 在指定列表的指定位置处交换元素
<T> void fill(List<? super T> list, T obj)
使用指定元素替换指定列表中的所有元素
<T> void copy(List<? super T> dest, List<? extends T> src)
将所有元素从一个列表复制到另一个列表
<T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
根据元素的自然顺序, 返回给定collection的最小元素
<T> T min(Collection<? extends T> coll, Comparator<? super T> comp)
根据指定比较器产生的顺序, 返回给定collection的最小元素
<T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
根据元素的自然顺序, 返回给定collection的最大元素
<T> T max(Collection<? extends T> coll, Comparator<? super T> comp)
根据指定比较器产生的顺序, 返回给定collection的最大元素
void rotate(List<?> list, int distance)
根据指定的距离轮换指定列表中的元素
<T> boolean replaceAll(List<T> list, T oldVal, T newVal)
使用另一个值替换列表中出现的所有某一指定值
int indexOfSubList(List<?> source, List<?> target)
返回指定源列表中第一次出现指定目标列表的起始位置; 如果没有出现这样的列表, 则返回 -1
int lastIndexOfSubList(List<?> source, List<?> target)
返回指定源列表中最后一次出现指定目标列表的起始位置; 如果没有出现这样的列表, 则返回 -1
<T> Collection<T> unmodifiableCollection(Collection<? extends T> c)
返回指定collection的不可修改视图
<T> Set<T> unmodifiableSet(Set<? extends T> s)
返回指定set的不可修改视图
<T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)
返回指定有序set的不可修改视图
<T> NavigableSet<T> unmodifiableNavigableSet(NavigableSet<T> s)
<T> List<T> unmodifiableList(List<? extends T> list)
返回指定列表的不可修改视图
<K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m)
返回指定映射的不可修改视图
<K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K, ? extends V> m)
返回指定有序映射的不可修改视图
<K,V> NavigableMap<K,V> unmodifiableNavigableMap(NavigableMap<K, ? extends V> m)
<T> Collection<T> synchronizedCollection(Collection<T> c)
返回指定collection支持的同步(线程安全的)collection
<T> Set<T> synchronizedSet(Set<T> s)
返回指定set支持的同步(线程安全的)set
<T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)
返回指定有序 set 支持的同步(线程安全的)有序set
<T> NavigableSet<T> synchronizedNavigableSet(NavigableSet<T> s)
<T> List<T> synchronizedList(List<T> list)
返回指定列表支持的同步(线程安全的)列表
<K,V> Map<K,V> synchronizedMap(Map<K,V> m)
返回由指定映射支持的同步(线程安全的)映射
<K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)
返回指定有序映射支持的同步(线程安全的)有序映射
<K,V> NavigableMap<K,V> synchronizedNavigableMap(NavigableMap<K,V> m)
<E> Collection<E> checkedCollection(Collection<E> c, Class<E> type)
返回指定collection的一个动态类型安全视图
<E> Queue<E> checkedQueue(Queue<E> queue, Class<E> type)
<E> Set<E> checkedSet(Set<E> s, Class<E> type)
返回指定set的一个动态类型安全视图
<E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type)
返回指定有序set的一个动态类型安全视图
<E> NavigableSet<E> checkedNavigableSet(NavigableSet<E> s, Class<E> type)
<E> List<E> checkedList(List<E> list, Class<E> type)
返回指定列表的一个动态类型安全视图
<K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType)
返回指定映射的一个动态类型安全视图
<K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K, V> m, Class<K> keyType, Class<V> valueType)
返回指定有序映射的一个动态类型安全视图
<K,V> NavigableMap<K,V> checkedNavigableMap(NavigableMap<K, V> m, Class<K> keyType, Class<V> valueType)
<T> Iterator<T> emptyIterator()
<T> ListIterator<T> emptyListIterator()
<T> Enumeration<T> emptyEnumeration()
<T> Set<T> emptySet() 返回空的set(不可变的)
<E> SortedSet<E> emptySortedSet()
<E> NavigableSet<E> emptyNavigableSet()
final <T> List<T> emptyList() 返回空的列表(不可变的)
final <K,V> Map<K,V> emptyMap() 返回空的映射(不可变的)
final <K,V> SortedMap<K,V> emptySortedMap()
final <K,V> NavigableMap<K,V> emptyNavigableMap()
<T> Set<T> singleton(T o) 返回一个只包含指定对象的不可变set
<T> List<T> singletonList(T o) 返回一个只包含指定对象的不可变列表
<K,V> Map<K,V> singletonMap(K key, V value)
返回一个不可变的映射, 它只将指定键映射到指定值
<T> List<T> nCopies(int n, T o)
返回由指定对象的n个副本组成的不可变列表
<T> Comparator<T> reverseOrder()
返回一个比较器, 它强行逆转实现了Comparable接口的对象collection的自然顺序
<T> Comparator<T> reverseOrder(Comparator<T> cmp)
返回一个比较器, 它强行逆转指定比较器的顺序
<T> Enumeration<T> enumeration(final Collection<T> c)
返回一个指定collection上的枚举
<T> ArrayList<T> list(Enumeration<T> e)
返回一个数组列表, 它按返回顺序包含指定枚举返回的元素
int frequency(Collection<?> c, Object o)
返回指定collection中等于指定对象的元素数
boolean disjoint(Collection<?> c1, Collection<?> c2)
如果两个指定collection中没有相同的元素, 则返回true
<T> boolean addAll(Collection<? super T> c, T... elements)
将所有指定元素添加到指定collection中
<E> Set<E> newSetFromMap(Map<E, Boolean> map)
返回指定映射支持的 set
<T> Queue<T> asLifoQueue(Deque<T> deque)
以后进先出(Lifo) Queue的形式返回某个Deque的视图
网友评论