文章目录
-
- 集合对比&选择
- 集合工具java.util.Collections
-
- 列表排序(指定顺序)
- 列表快速查询下标
- 反转列表
- 随机打乱列表
- 交换指定列表两个元素位置
- 填充list
- 拷贝集合(对元素而言是拷贝引用)
- 最大、最小值
- 集合出现次数(统计集合内元素的频次)
- map 转set
- 整体移动前n个元素到集合后面(或者后n个到前面)
- 不可变包装(用于集合元素固定不可修改)
- 同步集合包装(用于生成线程安全集合)
- 单元素集合包装(避免new 集合返回)/空集合包装 (避免反回null 或者new 集合)
- 探索java.util.Arrays#sort排序算法
集合对比&选择
通过前面几天的集合文章:
- 【面试专栏】第三篇:Java基础:集合篇-List、Queue
- 【面试专栏】第四篇:Java基础:集合篇-Map、HashMap、Hashtable
- 【面试专栏】第五篇:Java基础:集合篇-LinkedHashMap、ConcurrentHashMap、TreeMap
- 【面试专栏】第六篇:Java基础:集合篇-HashSet、TreeSet
- 【面试专栏】第七篇:Java基础:集合篇-LinkedHashSet、BitSet、CopyOnWriteArraySet
简单总结回顾一下:
Map 接口和 Collection 接口是所有集合框架的父接口;
Collection 接口的子接口包括:Set 接口、List 接口和Queue接口;
Map 接口的实现类主要有:HashMap、TreeMap、LinkedHashMap、Hashtable、ConcurrentHashMap 以及 Properties 等;
Set 接口的实现类主要有:HashSet、TreeSet、LinkedHashSet 等;
List 接口的实现类主要有:ArrayList、LinkedList、Stack 、Vector以及CopyOnWriteArrayList 等;
Queue接口的主要实现类有:ArrayDeque、ArrayBlockingQueue、LinkedBlockingQueue、PriorityQueue等;
- 有序选择List 、无序去重选择Set
- 有序选择TreeMap、无序选择HashMap
- 线程安全有:Vector、Stack、CopyOnWriteArrayList、Hashtable、ConcurrentHashMap、CopyOnWriteArraySet
- 线程安全优先选择:CopyOnWriteArrayList、CopyOnWriteArraySet、ConcurrentHashMap
今天再介绍一种新的方式集合工具类实现线程安全。
集合工具java.util.Collections
列表排序(指定顺序)
需要注意列表如果为空会npe
, 内部使用的其实是java.util.Arrays#sort,这个在后面单独介绍
- java.util.Collections#sort(java.util.List) 默认排序
- java.util.Collections#sort(java.util.List, java.util.Comparator<? super T>) 带参数,可以指定排序类(这里也是和jdk8 lambda 结合后很便捷的点)
列表快速查询下标
通过jdk封装的快速查询元素所在位置
- java.util.Collections#binarySearch(java.util.List<? extends java.lang.Comparable<? super T>>, T)
- java.util.Collections#binarySearch(java.util.List<? extends T>, T, java.util.Comparator<? super T>)
反转列表
- java.util.Collections#reverse
随机打乱列表
一些需要随机展示的场景需要打乱列表
- java.util.Collections#shuffle(java.util.List<?>)
交换指定列表两个元素位置
- java.util.Collections#swap(java.util.List<?>, int, int)
填充list
将指定元素填充满列表
- java.util.Collections#fill
拷贝集合(对元素而言是拷贝引用)
- java.util.Collections#copy
最大、最小值
内部循环一遍根据排序找出最大最小返回
- java.util.Collections#min(java.util.Collection<? extends T>)
- java.util.Collections#min(java.util.Collection<? extends T>, java.util.Comparator<? super T>)
- java.util.Collections#max(java.util.Collection<? extends T>)
- java.util.Collections#max(java.util.Collection<? extends T>, java.util.Comparator<? super T>)
集合出现次数(统计集合内元素的频次)
可以统计null的次数
- java.util.Collections#frequency
map 转set
- java.util.Collections#newSetFromMap
整体移动前n个元素到集合后面(或者后n个到前面)
当distance为正数时,将List集合的后distance个元素“整体”移到前面;当distance为负数时,将list集合的前distance个元素“整体”移到后边。该方法不会改变集合的长度。
- java.util.Collections#rotate
不可变包装(用于集合元素固定不可修改)
所有类型的集合都封装了一个对应的方法,实现原理就是内部实现了一个集合的方法,调用修改集合修改方法抛出异常
所以对于集合内对象的值是可以修改的,集合与对象的引用是不允许修改了
- java.util.Collections#unmodifiableCollection
- java.util.Collections#unmodifiableSet
- java.util.Collections#unmodifiableSortedSet
- java.util.Collections#unmodifiableList
- java.util.Collections#unmodifiableMap
- …
同步集合包装(用于生成线程安全集合)
生成一个线程安全的集合对象,实现原理就是内部实现了一个集合的同步方法,同步类就是集合自身引用,调用修改方法时 使用synchronized 锁住自身对象
拿一个举例
/**
* @serial include
*/
static class SynchronizedCollection<E> implements Collection<E>, Serializable {
private static final long serialVersionUID = 3053995032091335093L;
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;
}
SynchronizedCollection(Collection<E> c, Object mutex) {
this.c = Objects.requireNonNull(c);
this.mutex = Objects.requireNonNull(mutex);
}
public int size() {
synchronized (mutex) {return c.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return c.isEmpty();}
}
public boolean contains(Object o) {
synchronized (mutex) {return c.contains(o);}
}
public Object[] toArray() {
synchronized (mutex) {return c.toArray();}
}
public <T> T[] toArray(T[] a) {
synchronized (mutex) {return c.toArray(a);}
}
public Iterator<E> iterator() {
return c.iterator(); // Must be manually synched by user!
}
public boolean add(E e) {
synchronized (mutex) {return c.add(e);}
}
public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}
public boolean containsAll(Collection<?> coll) {
synchronized (mutex) {return c.containsAll(coll);}
}
public boolean addAll(Collection<? extends E> coll) {
synchronized (mutex) {return c.addAll(coll);}
}
public boolean removeAll(Collection<?> coll) {
synchronized (mutex) {return c.removeAll(coll);}
}
public boolean retainAll(Collection<?> coll) {
synchronized (mutex) {return c.retainAll(coll);}
}
public void clear() {
synchronized (mutex) {c.clear();}
}
public String toString() {
synchronized (mutex) {return c.toString();}
}
// Override default methods in Collection
@Override
public void forEach(Consumer<? super E> consumer) {
synchronized (mutex) {c.forEach(consumer);}
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
synchronized (mutex) {return c.removeIf(filter);}
}
@Override
public Spliterator<E> spliterator() {
return c.spliterator(); // Must be manually synched by user!
}
@Override
public Stream<E> stream() {
return c.stream(); // Must be manually synched by user!
}
@Override
public Stream<E> parallelStream() {
return c.parallelStream(); // Must be manually synched by user!
}
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();}
}
}
单元素集合包装(避免new 集合返回)/空集合包装 (避免反回null 或者new 集合)
这两种我认为是一种更优雅、更高性能(避免了创建很多个集合)的写法,但是需要注意在上层使用的时候不能直接添加元素,不然会抛出异常
。
单元素集合实现了集合方法,内部只保存一个元素
- java.util.Collections#singleton
- java.util.Collections#singletonList
- java.util.Collections#singletonMap
空集合实现了集合方法,内部不存储元素,同时设置了静态变量,全局只有一个空集合
- java.util.Collections#emptySet
- java.util.Collections#emptyMap
- …