Java基础 - 核心类库 - 集合类库
Java基础 - 核心类库 - 集合类库
1 集合概述
1.1 集合的由来
为什么需要集合?
- 当需要在Java程序中记录单个数据内容时,则声明一个变量
- 当需要在Java程序中记录多个类型相同的数据内容时,声明一个一维数组
- 当需要在Java程序中记录多个类型不同的数据内容时,则创建一个对象
- 当需要在Java程序中记录多个类型相同的对象数据时,创建一个对象数组
- 当需要在Java程序中记录多个类型不同的对象数据时,则准备一个集合
1.2 集合的框架结构
Java中集合框架顶层框架是:java.util.Collection集合 和 java.util.Map集合
- Collection集合基本存取单位为单个元素
- Map集合中基本存取单位为单对原始

1.3 Collection 集合
1.3.1 概念
java.util.Collection接口是List接口、Queue 接口以及Set接口的父接口,因此该接口里定义的方法 既可用于操作List集合,也可用于操作Queue集合和Set集合
1.3.2 常用方法
boolean add(E e); 向集合中添加对象
boolean addAll(Collection<? extends E>
c)
用于将参数指定集合c中的所有元素添加到当前集合
中
boolean contains(Object o); 判断是否包含指定对象
boolean containsAll(Collection<?> c) 判断是否包含参数指定的所有对象
boolean retainAll(Collection<?> c) 保留当前集合中存在且参数集合中存在的所有对象
boolean remove(Object o); 从集合中删除对象
boolean removeAll(Collection<?> c) 从集合中删除参数指定的所有对象
void clear(); 清空集合
int size(); 返回包含对象的个数
boolean isEmpty(); 判断是否为空
boolean equals(Object o) 判断是否相等
int hashCode() 获取当前集合的哈希码值
Object[] toArray() 将集合转换为数组
Iterator iterator() 获取当前集合的迭代器
- add 和 addAll 传入集合时得到的结果不一样,add将传入的集合看作一个整个
- contains 方法的工作原理时:Objects.equals(o,e), 该方法工作原理为:
Objects.equals(o,e)
//其中o代表contains方法的形式参数,e代表集合中的每个元素
//contains的原理是拿着形参o和集合中的每个元素依次使用Objects的equals方法比较
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
//该方法中a代表形参,b代表集合中的每个元素
//比较时先比较a和b的地址是否相同,相同则返回true
//如果a不等于null的情况下调用形参a中equals方法进行比较,如a中没重写equals方法则还是调用Object类中比较地址的equals方法
- contains 和 containsAll 的笔试考点
c2 [three, 4]
c1.containsAll(c2) //判断集合c1中是否拥有c2集合中的所有元素
c1.contains(c2) // 判断集合c1中是否拥有c2集合这个整体的元素
- retainAll 取调用该方法集合和参数集合的交集,如调用该方法集合发生改变则返回true
c1.retainAll(c2)
//若有交集,该方法执行完成后,c1中的元素变为交集,c2中元素不变
- remove 方法的工作原理和 contains 方法类似,还是Objects.equals(o,e)
- removeAll 方法从调用方法的集合中删除参数集合中的所有元素,本质是一个一个元素进行删除,有的元素则删除,没有的则不删除
c1 [2,3] c2 [3,4]
c1.remove(c2) //该方法删除的是一个整体,c1中没有进行删除
1.3.2.1 集合和数组间的相互转换
// 集合向数组的转换
Object[] array = collecton.toArray();
//打印数组
Arrays.toString(array)
// 数组向集合的转换
Collection collection = Arrays.asList(collection);
//打印集合 打印自动调用toString方法
collection
1.4 Iterator 接口
1.4.1 概念
- java.util.Iterator接口主要用于描述迭代器对象,可以遍历Collection集合中的所有元素
- java.util.Collection接口继承Iterator接口,因此所有实现Collection接口的实现类都可以使用该迭代器对象
1.4.2 常用方法
| 方法 | 说明 |
|---|---|
| boolean hasNext() | 判断集合中是否有可以迭代/访问的元素 |
| E next() | 用于取出一个元素并指向下一个元素 |
| void remove() | 用于删除访问到的最后一个元素 |
异常:ConcurrentModificationException
iterator = c.iterator();
while(iterator.hasNext()){
Object obj = iterator.next();
c.romeve(obj); //异常 ConcurrentModificationException
}
一个线程不能修改集合当另一个线程正在迭代该集合,该情况下迭代不确定
1.5 for each 循环
1.5.1 for each 循环的概念
- Java5推出了增强型for循环语句,可以应用数组和集合的遍历
- 是经典迭代的“简化版
1.5.2 语法格式
for(元素类型 变量名 : 数组/集合名称) {
循环体;
}
1.6 List 集合
1.6.1 概念
- java.util.List(接口)集合是Collection集合的子集合,该集合中允许有重复的元素并且有先后放入次序
- 主要实现类:ArrayList类、LinkedList类、Stack类、Vector类
1.6.1.1 List常用方法
void add(int index, E element) 向集合中指定位置添加元素
boolean addAll(int index, Collection<? extends E> c) 向集合中添加所有元素
E get(int index) 从集合中获取指定位置元素
int indexOf(Object o) 查找参数指定的对象
int lastIndexOf(Object o) 反向查找参数指定的对象
E set(int index, E element) 修改指定位置的元素
E remove(int index) 删除指定位置的元素
List subList(int fromIndex, int toIndex) 用于获取子List
- subList 包含左不包含右,方法的得到集合和原集合共用一块内存空间,子集合改动原数组也会改动
1.6.2 ArrayList
概念:
- 基于动态数组(自动扩容)进行数据管理的
- 支持下标访问,查找方便
- 增删不方便
源码解析:
// 新建ArrayList 时使用无参构造
List list = new ArrayList();
// 无参构造具体方法如下
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//其中elemetnData 是一个Object 类型的一位数组用来缓存
transient Object[] elementData; // non-private to simplify nested class access
// 后面的常量是一个空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
所以在new ArrayList对象时并没有申请数组的内存空间
//接着给集合中添加元素
list.add("one");
1.进入list.add("one") 方法
// 该方法调用add 方法,分别传入参数"one",空数组,数组值元数个数(0)
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
2.进入add(e, elementData, size) 方法,判断数组元素个数与元素是否相等,相等调用grow()方法开辟内存空间
private void add(E e, Object[] elementData, int s) {
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
3. 进入grow() 方法,数组元素个数加1后再调用grow方法
private Object[] grow() {
return grow(size + 1);
}
4. 进入 grow(size + 1) 方法,该方法将原数组拷贝并放到新数组中
private Object[] grow(int minCapacity) {
return elementData = Arrays.copyOf(elementData,
newCapacity(minCapacity));
}
5. 进入 newCapacity(minCapacity) 申请数组内存空间
private int newCapacity(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length; //缓存数组的长度
int newCapacity = oldCapacity + (oldCapacity >> 1); //新的数组为缓存数组长度的1.5倍
if (newCapacity - minCapacity <= 0) { //初始化时
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) //如果缓存数组为空数组
return Math.max(DEFAULT_CAPACITY, minCapacity); //该常量值为10,在该常量和minCapacity中选择大的,初始长度为10
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return minCapacity;
}
return (newCapacity - MAX_ARRAY_SIZE <= 0) //该常量为2147483647 - 8,没超过该值返回扩容1.5倍之后的数组
? newCapacity
: hugeCapacity(minCapacity);
}
1.6.3 LinkedList
概念:
- 基于双向链表进行数据管理的
- 查找不方便,增删元素方便
源码解析
1. 调用无参构造构建一个空链表
public LinkedList() {
}
2. LinkedList 里size用来记录链表的长度,first用来指向链表的第一个节点,last用来指向链表的最后一个节点
transient int size = 0;
/**
* Pointer to first node.
*/
transient Node<E> first;
/**
* Pointer to last node.
*/
transient Node<E> last;
3. 空链表构造完成后执行add方法,尾插法,在最后一个节点后插入
public boolean add(E e) {
linkLast(e);
return true;
}
4.声明一个节点l(相当于指针指向链表的最后一个节点last,并新建一个节点newnode,然后将最后一个节点last指向新节点,并判断l指针是否为空,为空将头指针也指向新节点,不为空则将上一个节点的next指向新节点
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
4.1. new Node<>(pre,data,next)该构造创建了一个新的节点
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
1.6.3.1 常用方法
/1. 头插法
void add(0,obj) / void addFirst(obj) / void push(obj)
/2. 尾插法
boolean add(obj) / void addLast(obj)
/3. 查找但不删除
E get(int index)/getFirst()/getLast()
/4. 查找并删除
E remove()/remove(int index)/remove(Object o)/romoveFirst()/removeLast() / boolean removeFirstOccurrence(obj)/removeLastOccurrence(obj)
1.6.4 ArrayList 和 LinkedList的区别
- 方法在逻辑上完全一样
- 性能上有差别:
- ArrayList 更适合访问
- LinkedList 更适合插入和删除
1.6.5 Stack
概念:
- 基于动态数组进行数据管理
- 具有后进先出特征的数据结构,即栈(last in first out LIFO)
- 被Deque 接口及其实现类取代
1.6.5.1 常用方法
| 方法 | 说明 |
|---|---|
| boolean empty() | 判断栈是否为空 |
| E peek() | 查看栈顶元素但不移除 |
| E pop() | 移除栈顶元素并返回该值 |
| E push(E item) | 入栈/压栈 |
| int search(Object o) | 查找元素并返回位置 |
- 可以通过两个栈拿到栈中数据的原顺序
stack1 //[1,2,3,4]
stack2 //[]
stack2.push(stack1.pop())
stack2 //[4,3,2,1]
stack.pop //1,2,3,4
1.6.6 Vector
概念:
- 基于动态数组进行数据管理(扩容机制 *2)
- 被ArrayList取代,和ArrayList相比线程安全,效率较低
1.7 Queue集合
概念:
- java.util.Queue集合是Collection集合的子集合,与List集合属于平级关系
- 描述具有先进先出特征的数据结构,叫做队列(first in first out FIFO)
- 该集合的主要实现类是LinkedList类,因为该类在增删方面比较有优势
1.7.1 Queue 实现类 LinkedList 常用方法
/1. 插入元素至队尾,成功返回true
boolean offer(E e) = offerLast(E e) / offerFirst(E e) 从队首插入
/2. 从队首删除元素并返回
E poll() = pollFirst() / pollLast() 从队尾删除
/3. 查看队首元素但不删除
E peek() = peekFirst() / peekLast() 查看队尾但不删除
1.8 Set 集合
1.8.1 泛型
1.8.1.1 泛型的概念
- 集合能存放不同类型的对象因为将所有对象看作Object,取出使用需要将Object类型强制转为实际类型可能引发类型转换异常
- 为了避免上述错误的发生,从Java5开始增加泛型机制,也就是在集合名称的右侧使用<数据类型> 的方式来明确要求该集合中可以存放的元素类型,若放入其它类型的元素则编译报错
- 泛型只在编译时期有效,在运行时期不区分是什么类型
- Java 7 开始新特性,菱形特性,后面<>中的数据类型可以省略
泛型的原理:
泛型的本质就是参数化类型,也就是让数据类型作为参数传递,其中E相当于形式参数负责占位, 而使用集合时<>中的数据类型相当于实际参数,用于给形式参数E进行初始化,从而使得集合中所 有的E被实际参数替换,由于实际参数可以传递各种各样广泛的数据类型,因此得名为泛型
1.8.1.2 自定义泛型类
作用:可以用泛型来占位,并将成员变量定义为该泛型类,在声明该类时给该成员变量确定类型
- 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型
- 子类除了指定或保留父类的泛型,还可以增加自己的泛型
泛型类被继承时的处理方式
(1)不保留泛型且没有指定类型,此时父类中的T默认为Object类型 (擦除)
- 使用该泛型子类时不能再指定泛型类型(不支持泛型),泛型修饰的变量类型为Object
public class Son extends Father {}
(2)不保留泛型但指定了泛型的类型,此时父类中的T被指定为指定的类型
- 使用该泛型子类时不能再指定泛型类型(不支持泛型),泛型修饰的变量类型为指定的类型
public class Son extends Father<String> {}
(3)保留父类的泛型
- 可以在构造对象时指定T的类型
public class Son<T> extends Father<T> {}
(4)保留父类的泛型,同时在子类中增加新的泛型
public class Son<T,T1> extends Father<T> {}
注意:List<String> 并不是 List<Object> 的子类
1.8.1.3 自定义泛型方法
泛型方法的格式:
[访问权限] <泛型> 返回值类型 方法名(泛型标识 参数名称) { 方法体; }
在静态方法中使用泛型参数的时候,需要我们把静态方法定义为泛型方法
public class XXX <T> {
public static T xxx(){
方法体;
}
}
//以上代码编译不通过,该方法返回值为泛型,需要在new对象时对泛型赋值,加了static可以不赋值直接调用,所以不能
//正确用法
public static <T> 返回值类型 xxx(T 参数名){ 方法体 }
1.8.1.4 通配符
概念:
- 望传入的类型在一个指定的范围内,使用泛型通配符
泛型中通配符的形式(3种):
(1) <?> :无限制通配符:可传入任意类型的参数
该通配符可以作为泛型类型的公共父类,
List<String> list1 可以转换为 List<?> list2
但是list2不能调用add方法,因为?表示任意类型,传入具体类型不符合
支持取出元素,全部当作Object来处理
(2) <? extends E>:表示类型的上界是E,只能是E或者是E的子类
同样不支持add(E)方法,因为上界是E,所以可能是E的子类
取出元素全部当作E类型来处理
(3)<? super E>: 表示类型的下界是E,只能是E或者是E的父类
支持add(E)及其子类方法,因为下界是E
取出元素全部当成Object类型来处理
1.8.2 Set 接口
概念:
- java.util.Set集合是Collection集合的子集合,与List集合平级
- 该集合中元素没有先后放入次序(不代表随机),且不允许重复
- 该集合的主要实现类包括
- HashSet 类
- TreeSet 类
- LinkedHashSet 类
- LinkedHashSet类与HashSet类的不同之处在于内部维护了一个双向链表,链表中记录了元 素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代
1.8.2.1 HashSet 类
概念:
- 基于哈希表进行数据管理的
常用方法:
boolean add(E e) 如果指定元素不存在,则将其添加到此集合中。
void clear() 从该集中删除所有元素。
Object clone() 返回此HashSet实例的浅表副本:未克隆元素本身。
boolean contains(Object o) 如果此set包含指定的元素,则返回true
boolean isEmpty() 如果此集合不包含任何元素,则返回 true 。
Iterator<E> iterator() 返回此set中元素的迭代器。
boolean remove(Object o) 如果存在,则从该集合中移除指定的元素。
int size() 返回此集合中的元素数(基数)
元素放入HashSet集合的原理
- 使用元素调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算出该元素在数组中的索引位置
- 若该位置没有元素,则将该元素直接放入即可
- 若该位置有元素,则使用新元素与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放 入
- 若新元素与已有元素的哈希值相同,则使用新元素调用equals方法与已有元素依次比较
- 若相等则添加元素失败,否则将元素直接放入即可。
为什么要求重写equals方法后要重写hashCode方法呢?
- 当两个元素调用equals方法相等时证明这两个元素相同,重写hashCode方法后保证这两个元 素得到的哈希码值相同,由同一个哈希算法生成的索引位置相同,此时只需要与该索引位置已有元素比较即可,从而提高效率并避免重复元素的出现
1.8.2.2 TreeSet 类
概念:
- 红黑树进行数据管理
- 当有新元素插入到TreeSet集合时,需要使用新元素与集合中已有的元素依次比较来确定新元素的合理位置
比较元素大小的两种规则:
自然排序
- 使用元素的自然排序规则进行比较并排序,让元素类型实现java.lang.Comparable接口
- 当TreeSet中放入的类型是String 类型时会自动排序,因为String 实现类Comparable
接口 - 传入自定义类时需要实现Comparable<自定义类>接口并重写compareTo 方法
- return 0 //调用对象和参数对象相等,调用对象就是新增对象
- return 1 //调用对象大于参数对象
- return -1 //调用对象小于参数对象
比较器规则
- 使用比较器规则进行比较并排序,构造TreeSet集合时传入java.util.Comparator接口
- 构造方法TreeSet(Comparator<? super E> comparator)
//1. 匿名内部类
Comparator<指定类> comparator = new Comparator<指定类>() {
@Override
public int compare(指定类 o1, 指定类 o2) { //o1表示新增对象,o2表示集合中已有对象
return 0;
}
};
//2. Lambda表达式
Comparator<指定类> comparator1 = (指定类 o1, 指定类 o2) -> {return 0;};
1.9 Map 集合
基本概念:
-
java.util.Map 基本单位为单对元素,参数类型为:
- K - 此映射所维护的键(Key)的类型,相当于目录
- V - 映射值(Value)的类型,相当于内容
-
key 与 value 是一一对应的且key的值不允许重复
-
主要实现类有:
- HashMap 类
- LinkedHashMap 类
- TreeMap 类
- HashTable 类
- Properties 类
-
Map集合是面向查询优化的数据结构, 在大数据量情况下有着优良的查询性能,常用于根据key 检索value的业务
常用方法:
V put(K key, V value) 将Key-Value对存入Map,若集合中已经包含该Key,则替换该Key所对应的Value,返回值为该Key原来所对应的Value,若没有则返回null
V get(Object key) 返回与参数Key所对应的Value对象,如果不存在则返回null
boolean containsKey(Object key); 判断集合中是否包含指定的Key
boolean containsValue (Object value); 判断集合中是否包含指定的Value
V remove(Object key) 根据参数指定的key进行删除
Set keySet() 返回此映射中包含的键的Set视图
Collection values() 返回此映射中包含的值的Set视图
Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射的Set视图
1.9.1 HashMap 类
概念:
- 哈希表进行数据管理
1.9.1.1 HashMap 和 HashSet之间的关系
- set 集合中的元素作为map集合中的key,map 集合中的value 使用 new Object() 进行占位
//1. 构建HashSet 集合时底层时新建了一个HashMap
public HashSet() {
map = new HashMap<>();
}
//2. 向HashSet中添加元素实际上是向map中的key添加元素
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
//3. PRESENT 使用 new Object() 进行占位
private static final Object PRESENT = new Object();
1.9.1.2 常用方法
除了Map 集合的常用方法外,还包括:
void putAll(Map<? extends K, ? extends V> m) 复制指定的map集合
int size() 返回集合中键值对的数量
1.9.1.3 HashMap 放入元素的原理
- 使用元素的key调用hashCode方法获取对应的哈希码值,再由某种哈希算法计算在数组中的索引位置
- 若该位置没有元素,则将该键值对直接放入即可
- 若该位置有元素,则使用key与已有元素依次比较哈希值,若哈希值不相同,则将该元素直接放 入
- 若key与已有元素的哈希值相同,则使用key调用equals方法与已有元素依次比较
- 若相等则将对应的value修改,否则将键值对直接放入即可
1.9.1.4 HashMap 相关常量
- DEFAULT_INITIAL_CAPACITY : HashMap的默认容量是16
- DEFAULT_LOAD_FACTOR:HashMap的默认加载因子是0.75
- threshold:扩容的临界值,该数值为:容量*填充因子,也就是12
- TREEIFY_THRESHOLD:若Bucket中链表长度大于该默认值则转化为红黑树存储,该数值是8
- MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量,该数值是64
设置临界值让数组扩容的目的是为了增加数组的下标从而让每一个下标上的数组尽可能的少,提高遍历的效率
1.9.1.5 元素放入Map集合源码分析
// 1.创建HashMap对象调用构造方法,没有申请数组,只给定了默认的加载因子
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
// 2.
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
// 3. 进入hash(key) 方法, 该方法先使用hashCode()方法计算哈希码值,再根据哈希算法计算出哈希值
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
// 4. putVal()方法参数为key,value和key的哈希值,该方法中table为node类型的数组用来存放元素
transient Node<K,V>[] table;
// 5. 一开始table数组为空,resize()方法申请内存空间
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 6. 进入resize()方法,DEFAULT_INITIAL_CAPACITY默认值为1 << 4(16)
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
//7. 通过哈希值运算得到数组中的下标位置,如果该位置为空,直接将该键值对放入该位置
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
//8. 如果下标位置不为空,则判断哈希值和equals方法判断对象是否相等,都相等的话将其旧值记录起来(oldvalue),并将旧值改为新值(e.value=value),再返回旧值
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
//9. 如果下标位置不相等,哈希值和equals判断对象不相等,则使用一个循环继续往后找,如果没有找到且没有找到该位置的最后一个节点,指向下一个节点继续寻找,如果找到了就跳出循环(将该节点的值带到后面的方法中去替换),如果找到最后一个节点还没找到则直接拼接在最后,如果链长度超过8则变为红黑树
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
1.9.1.6 Map 集合遍历方式
- Map集合没有继承iterator 接口所以不能使用迭代器和foreach 方法,要遍历需要先转为set集合
(1)Set keySet() 方法
(2)Collection values() 方法
(3)Set<Map.Entry<K,V>> entrySet() 方法
- Entry 是 Map 接口中的一个内部接口
(4)toString() 方法
- 用的是父类AbstractMap 中的 toString, 其还是使用 entrySet
1.10 Collecions 类
概念:
- java.util.Collections类主要提供了对集合操作或者返回集合的静态方法
常用方法:
1. static <T extends Object & Comparable<? super T>> T
max(Collection<? extends T> coll)
根据元素的自然顺序返回给定集合的最大元素
2. static T max(Collection<? extends T> coll, Comparator<?super T> comp)
根据指定比较器引发的顺序返回给定集合的最大元素
3. static <T extends Object & Comparable<?super T>> T
min(Collection<? extends T> coll)
根据元素的自然顺序返回给定集合的最小元素
4. static T min(Collection<? extends T> coll, Comparator<?super T> comp)
根据指定比较器引发的顺序返回给定集合的最小元素
5. static void copy(List<? super T> dest, List<? extends T> src)
将一个列表中的所有元素复制到另一个列表中 (后拷贝到前)
6. static void reverse(List<?> list) 反转指定列表中元素的顺序
7. static void shuffle(List<?> list) 使用默认的随机源随机置换指定的列表
8. static <T extends Comparable<? super T>> void sort(List list)
根据其元素的自然顺序将指定列表按升序排序
9. static void sort(List list, Comparator<? super T> c)
根据指定比较器指定的顺序对指定列表进行排序
10.static void swap(List<?> list, int i, int j) 交换指定列表中指定位置的元素
拷贝数组时遇到的问题:
java.lang.IndexOutOfBoundsException: Source does not fit in dest
//拷贝不成功,因为集合list2的内存空间还没初始化
Integer[] in = {10,20,30,40};
List<Integer> list1 = Arrays.asList(in);
ArrayList<Integer> list2 = new ArrayList<>(10);
Collections.copy(list2,list1);
//换一种声明方式
List<Integer> list3 = Arrays.asList(new Integer[in.length]);

浙公网安备 33010602011771号