集合补充
集合工具类在java.util下,此类仅由静态方法组合或返回集合。
它包含对集合进行操作的多态算法,“包装器”,返回由指定集合支持的新集合。
如果提供给它们的集合或类对象为null,则此类的方法都抛出一个NullPointerException
1. 工具类
1.1 排序
返回值 | 方法 | 解释 |
---|---|---|
void | reverse(List<?> list) | 反转元素的顺序 |
void | sort(List |
排序 |
void | sort(List |
根据比较器排序 |
void | swap(List<?> list, int i, int j) | 交换元素位置 |
1.2 查找和替换
针对的是Collection接口
返回值 | 方法 | 解释 |
---|---|---|
int | binarySearch(List list, Object key) | 二分查找返回索引,前提是用sort排好序了 |
void | copy(List dest, List src) | 将所有元素从一个list复制到另一个list |
void | fill(List list, T obj) | 填充 |
int | frequency(Collection c, Object o) | 指定元素出现的次数 |
int | indexOfSubList(List source, List target) | 返回第一次出现的位置 |
1.3 同步
返回值 | 方法 | 解释 |
---|---|---|
List | synchronizedList(List list) | 返回同步集合 |
Set | synchronizedSet(Set set) | 返回同步集合 |
Map | synchronizedMap(Map map) | 返回同步集合 |
这里同步其实就是在每个方法里面加synchronized ,同一个对象锁(final Object mutex),用了装饰者模式,现在不推荐使用了,下面列举一个例子
static class SynchronizedCollection<E> implements Collection<E>, Serializable {
final Collection<E> c; // Backing Collection
final Object mutex; // Object on which to synchronize
//装饰器,获取被装饰对象
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
//装饰功能,加了锁,调用子类方法
public int size() {
synchronized (mutex) {return c.size();}
}
}
如果用到Iterator迭代器,需要自行加锁,因为这个上面没有加锁
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext()) {
//foo(i.next());
System.out.println(i.next());
}
}
2. JUC并发包
java.util.concurrent,下面试着随便说说ConcurrentHashMap
-
1.7用Segment分段锁,1.8用部分锁,下面用1.8讲解
-
采用数组+链表+红黑树的数据结构
-
synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,提高并发,不是锁整个表
-
检索操作不用加锁,get方法是非阻塞的
-
key和value都不允许为null
-
采用 锁头部 + CAS 实现
-
CAS无锁算法,使用volatile保证可见性,然后对比当前值与内存是否相等,相等才修改,多个线程对同一变量修改时,只有一个能成功
网络图(侵删)
3. 数组转集合
返回值 | 方法名 | 解释 |
---|---|---|
List | Arrays.asList(T... a) | 返回数组的List集合 |
- 若传参是普通类型的数组,List会把整个数组放到第一个元素里
- 返回指定数组的固定大小的List,而且不能改变结构,因为此处的List不是util下的,是Arrays下的,没有实现增删元素
- 若要互转 List list= new ArrayList( Arrays.asList(array) )
4. 迭代
如果不是并发的集合,迭代的时候不允许修改结构,会有快速失败机制,这个机制尽可能抛出并发修改错误,但不保证成功
5.RandomAccess接口
public interface RandomAccess {
}
主要功能是标识具有随机访问功能,有什么作用?别急
先判断传入list是否支持是否是的RamdomAccess的子类
是则调用indexedBinarySearch()方法
否则调用iteratorBinarySearch()方法,iteratorBinarySearch是专门处理链表的
6.HashMap 与 HashSet计算Hash的区别
HashMap使用键(Key)计算Hashcode, HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性
7.HashSet如何检查重复
当你把对象加入HashSet
时,HashSet会先计算对象的hashcode
值来判断对象加入的位置,同时也会与其他加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()
方法来检查hashcode相等的对象是否真的相同。如果两者相同,HashSet就不会让加入操作成功