## 集合框架
为什么要用集合而非数组:
虽然数组是保存一组对象最有效的方式,但是数组具有固定尺寸,但在写程序时并不知道将需要多少个对象。而集合能够自动地调整自己的尺寸。
打印数组时,必须使用`Arrays.toString()`,但是打印集合可以直接打印。
创建集合对象如果使用泛型,那么默认可以存放所有Object对象
使用泛型可以应用向上转型机制。
![img](https://img-blog.csdnimg.cn/20190310181825411.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2Rpd2Vpa2FuZw==,size_16,color_FFFFFF,t_70)
### Collection:一个独立元素的序列
Collection接口包括以下方法:
```java
boolean add(E a);
boolean addAll(Collection extend E> c);
int size();
boolean isEmpty();
boolean remove(Object o);
boolean removeAll(Collection> c);
boolean contains(Object o);
boolean containsAll(Clooection> c);
void clear();
Iterator iterator();
toArray(); //重载了几个
```
#### List(有序可重复)
`List`接口的常用方法:
- 在末尾添加一个元素:`boolean add(E e)`
- 在指定索引添加一个元素:`boolean add(int index, E e)`
- 删除指定索引的元素:`int remove(int index)`
- 删除某个元素:`int remove(Object e)`
- 获取指定索引的元素:`E get(int index)`
- 获取链表大小(包含元素的个数):`int size()`
- 获取指定元素的索引:`int indexOf(Object o)`,不存在会返回-1
实现了`List`两类数据结构:
- `ArrayList`(常用)
- 特性:擅长随机访问
- `LinkedList`(常用)
- 定义:除了实现了`List`接口,还实现了`Deque`接口,可用作栈、队列、双列
- 特性:擅长插入插出
> 以下类不应该继续使用
>
> - Vector:一种线程安全的`List`实现
> - Stack:基于`Vector`实现的`LIFO`的栈
##### List和Array相互转换
使用`toArray(T[] array)`将`List`转换为`Array`:
```java
//不使用参数,默认转换为Object类型
List list = List.of(1, 2, 3, 4);
Object[] arrs = list.toArray();
//由于将Object类强转为其他类型数组可能出来ClassCastException错误,强制使用带参数的方法
//带参转换,传入的是类型完全一致、长度为0的空数组
List list = List.of(1, 2, 3, 4);
Integer[] arrs = list.toArray(new Integer[0]);
```
使用`List.of(T...)`返回的是一个只读`List`,不能对返回的`List`进行操作,否则抛出`UnsupportedOperationException`异常。
使用`Arrays.asList(T...)`返回一个`List`,此`List`可操作
```java
List list = Arrays.asList(1, 2, 3);
```
#### `Set`(无序不可重复)
- `HashSet`(常用)
- `TreeSet`(有序)
#### Queue(接口)
- `int size()`:获取队列长度;
- `boolean add(E)`/`boolean offer(E)`:添加元素到队尾,前者失败时会抛出异常;
- `E remove()`/`E poll()`:获取队首元素并从队列中删除,前者失败时会抛出异常;
- `E element()`/`E peek()`:获取队首元素但并不从队列中删除;
`LinkedList`实现了`Queue`接口,可以使用`Queue`引用`LinkedList`:
```java
Queue queue = new LinkedList<>();
```
#### Deque(双端队列,接口,继承Queue)
- `boolean addLast(E e)` / `boolean offerLast(E e)`:添加元素到队尾,前者失败时会抛出异常;
- `E removeFirst() `/ `E pollFirst()`:获取队首元素并从队列中删除,前者失败时会抛出异常;
- `E getFirst()` / `E peekFirst()`:获取队首元素但并不从队列中删除;
- `boolean addFirst(E e)` / `boolean offerFirst(E e)`添加元素到队头,前者失败时会抛出异常;
- `E removeLast()` /`E pollLast()`:获取队尾元素并从队列中删除,前者失败时会抛出异常;
- `E getLast() `/ `E peekLast()`:获取队尾元素但并不从队列中删除;
`Deque`用作栈,取代`Stack`:
- `void push()`:将一个元素压入栈顶
- `E pop()`:从栈顶弹出已给元素
`LinkedList`实现了`Deque`接口,可以使用`Deque`引用`LinkedList`:
```java
Deque deque = new LinkedList<>();
```
#### PriorityQueue(优先队列)
```java
PriorityQueue pq = new PriorityQueue<>();
pq.add(3);
pq.add(1);
pq.add(4);
pq.add(2);
System.out.println(pq.poll()); // 1
System.out.println(pq.poll()); // 2
System.out.println(pq.remove()); // 3
```
### Map:一组成对的“键值对”对象
`Map`是一种键值映射表,使用:
- `V put(K key, V value)`:把`key`和`value`做了映射并放入`Map`中
- `V get(K key)`:通过`key`获取到对应的`value`。如果`key`不存在,则返回`null`。
- `boolean containsKey(K key)`:查询某个`key`是否存在
- `boolean containsValue(V value)`:查询某个`value`是否存在
遍历`Map`:
使用`for each`循环遍历`Map`实例的`keySet()`方法返回的`Set`集合
```java
Map map = new HashMap<>();
map.put("one", 1);
map.put("two", 2);
map.put("three", 3);
for (String key : map.keySet()) {
Integer value = map.get(key);
System.out.println(key + " = " + value);
}
```
使用`for each`循环遍历`Map`对象的`entrySet()`集合同时遍历`key`和`value`:
```java
Map map = new HashMap<>();
map.put("apple", 123);
map.put("pear", 456);
map.put("banana", 789);
for (Map.Entry entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + " = " + value);
}
```
HashMap(天天用,JDK1.7 数组+链表,JDK1.8以后 数组+链表+红黑树)
put(key, value)
LinkedHashSet:按照被添加的顺序保存对象
TreeMap:按比较结果升序保存对象
`Hashtable`
### 迭代器(Interator)
迭代器是一个轻量级对象,它的工作是遍历并选择序列中的对象。使用迭代器遍历集合是最高效的方式,`for each`就是使用迭代器遍历的。
Java的`Iterator`只能单向移动,用来:
- 使用方法`iterator()`要求容器返回一个`Iterator`
- 使用`next()`获得序列中的下一个元素
- 使用`hasNext()`检查序列中是否还有元素
- 使用`remove()`将迭代器新近返回的元素删除
Java的`listIterator`可以双向移动(只有List有):
- 使用方法`listIterator()`要求容器返回一个`ListIterator`
- `hasNext()`和`hasPrevious()`查看是否还有下一个和上一个元素
- `next()`和`previous()`可以获得序列中的下一个元素和上一个元素
- 使用`set()`可以替换新近访问的元素
- 使用`remove()`将迭代器新近返回的元素删除
### Collections工具类(类似于Arrays)
常用的一些方法:
- `Collections.sort(List)`:排序
- `Collections.reverse(List)`:翻转
- `Collections.shuffle(List)`:打乱
- `Collections.fill(List, Object)`:用给定对象填充`List`的所有元素
- `Collections.max/min(List)`:返回最大/最小值
- `Collections.swap(List list,int i,int j)`:交换集合中指定元素索引的位置