构造方法
private Lists() {
}
私有的构造方法,可以看到这是一个真正的功能函数,下面对其函数进行分析
功能函数
首先根据每一个函数的更能进行了分类:
创建ArrayList方法 | newArrayList() newArrayList(E... elements) newArrayList(Iterable<? extends E> elements) newArrayList(Iterator<? extends E> elements) newArrayListWithCapacity(int initialArraySize) newArrayListWithExpectedSize(int estimatedSize) |
创建LinkedList方法 | newLinkedList() newLinkedList(Iterable<? extends E> elements) |
创建CopyOnWriteArrayList方法 | newCopyOnWriteArrayList() newCopyOnWriteArrayList(Iterable<? extends E> elements) |
创建自制List规则 | asList(@Nullable E first, E[] rest) asList(@Nullable E first, @Nullable E second, E[] rest) |
对多个List做笛卡尔乘积 | cartesianProduct(List<? extends List<? extends B>> lists) cartesianProduct(List<? extends B>... lists) |
从做个类型的List转到另一个类型的List方法 | transform(List<F> fromList, Function<? super F, ? extends T> function) |
对list进行分批输出的方法(作用之一:分页) | partition(List<T> list, int size) |
将字符串作为字符数组进行操作 | charactersOf(String string) charactersOf(CharSequence sequence) |
将list逆序 | reverse(List<T> list) |
下面对每一类进行源码解析:
创建ArrayList方法
- 没有参数的创建ArrayList
public static <E> ArrayList<E> newArrayList() {
return new ArrayList();
}
查看源码可以看到,直接返回一个新的ArrayList容器
- 传入一个数组,返回一个ArrayList
public static <E> ArrayList<E> newArrayList(E... elements) {
//对数组进行判空处理
Preconditions.checkNotNull(elements);
// computeArrayListCapacity对当前数量进行优化
int capacity = computeArrayListCapacity(elements.length);
//这里根据优化后的数量进行创建一个新的ArrayList
ArrayList list = new ArrayList(capacity);
//将数组里面的元素都存储在List中
Collections.addAll(list, elements);
return list;
}
有上面,我们可以解析一下computeArrayListCapacity方法:
static int computeArrayListCapacity(int arraySize) {
//判断是否小于0,小于0则抛出异常
CollectPreconditions.checkNonnegative(arraySize, "arraySize");
// saturatedCast函数判断计算出来的数组长度是否在int的范围内
return Ints.saturatedCast(5L + (long)arraySize + (long)(arraySize / 10));
}
可以看到对于传入的数值进行运算:5L+arraysize+(arraysize/10)
可以拿一个10长度的数组进行测试,优化后的list长度为16
优点:节约内存,节约时间,节约性能。代码质量提高
saturatedCast函数的源码
public static int saturatedCast(long value) {
return value > 2147483647L?2147483647:(value < -2147483648L?-2147483648:(int)value);
}
3.传入一个集合顶级接口,然后返回一个ArrayList
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
//对集合进行判空
Preconditions.checkNotNull(elements);
//根据传入的实际类型,进行分别处理
return elements instanceof Collection?new ArrayList(Collections2.cast(elements)):newArrayList((Iterator)elements.
iterator());
}
4.传入一个迭代器,返回一个ArrayList
public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
ArrayList list = newArrayList();
//根据Iterators中的addAll方法将迭代器中的源码装入list集合中
Iterators.addAll(list, elements);
return list;
}
最终是由Iterators中的addAll方法进行的数据转移操作
5.传入想要的list长度,返回一个与传入值等长的ArrayList
public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
CollectPreconditions.checkNonnegative(initialArraySize, "initialArraySize");
return new ArrayList(initialArraySize);
}
可以看到源码直接返回一个新的ArrayList,并且长度为传入的长度
6.传入一个想要的list长度,返回一个程序调优后的长度的ArrayList
public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
return new ArrayList(computeArrayListCapacity(estimatedSize));
}
computeArrayListCapacity函数的计算公式上面介绍过了,这里直接返回一个长度调优后的ArrayList
创建LinkedList方法
- 不传入参数,直接返回一个LinkedList
public static <E> LinkedList<E> newLinkedList() {
return new LinkedList();
}
如源码所示,直接返回一个LinkedList
- 传入一个容器,返回一个LinkedList
public static <E> LinkedList<E> newLinkedList(Iterable<? extends E> elements) {
LinkedList list = newLinkedList();
Iterables.addAll(list, elements);
return list;
}
可以看到源码中,将传入的容器,使用Iterables的addAll方法进行的数据转移
创建CopyOnWriteArrayList方法
- 不传入参数,直接返回一个新的CopyOnWriteArrayList
public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList() {
return new CopyOnWriteArrayList();
}
- 传入一个容器,返回一个CopyOnWriteArrayList,带有传入容器的值
public static <E> CopyOnWriteArrayList<E> newCopyOnWriteArrayList(Iterable<? extends E> elements) {
Object elementsCollection = elements instanceof Collection?Collections2.cast(elements):newArrayList((Iterable)elements);
return new CopyOnWriteArrayList((Collection)elementsCollection);
}
创建自制List规则
- 根据参数生成一个多一个参数的List
public static <E> List<E> asList(@Nullable E first, E[] rest) {
return new Lists.OnePlusArrayList(first, rest);
}
返回一个Lists中的内部类OnePlusArrayList,下面进行解析OnePlusArrayList的源码
private static class OnePlusArrayList<E> extends AbstractList<E> implements Serializable, RandomAccess {
final E first;
final E[] rest;
private static final long serialVersionUID = 0L;
OnePlusArrayList(@Nullable E first, E[] rest) {
this.first = first;
this.rest = (Object[])Preconditions.checkNotNull(rest);
}
public int size() {
return this.rest.length + 1;
}
public E get(int index) {
Preconditions.checkElementIndex(index, this.size());
return index == 0?this.first:this.rest[index - 1];
}
}
可以看到OnePlusArrayList类进行重写了size和get方法。因为是比原来数组多1个数,所以size方法在原来的基础上进行了+1操作。对get的重写是将所有的下标逻辑上后移了一位。
- 根据参数生成一个多两个个参数的List
public static <E> List<E> asList(@Nullable E first, @Nullable E second, E[] rest) {
return new Lists.TwoPlusArrayList(first, second, rest);
}
返回一个Lists中的内部类TwoPlusArrayList,下面进行解析TwoPlusArrayList的源码
private static class TwoPlusArrayList<E> extends AbstractList<E> implements Serializable, RandomAccess {
final E first;
final E second;
final E[] rest;
private static final long serialVersionUID = 0L;
TwoPlusArrayList(@Nullable E first, @Nullable E second, E[] rest) {
this.first = first;
this.second = second;
this.rest = (Object[])Preconditions.checkNotNull(rest);
}
public int size() {
return this.rest.length + 2;
}
public E get(int index) {
switch(index) {
case 0:
return this.first;
case 1:
return this.second;
default:
Preconditions.checkElementIndex(index, this.size());
return this.rest[index - 2];
}
}
}
根据源码可以看到,TwoPlusArrayList重写了size和get两个方法,size在实际数组长度上进行了+2的操作,get则在逻辑上将下标进行了后移两位
对多个List做笛卡尔乘积
从做个类型的List转到另一个类型的List方法
public static <F, T> List<T> transform(List<F> fromList, Function<? super F, ? extends T> function) {
return (List)(fromList instanceof RandomAccess?new Lists.TransformingRandomAccessList(fromList, function):new Lists.TransformingSequentialList(fromList, function));
}
看源码可以知道,程序会根据传入的List属于什么类型进行分类处理,不过无论使用哪种方式进行处理,在他们的实现类中都重写了listIterator方法,下面我们主要对这个方法进行分析:
private static class TransformingRandomAccessList<F, T> extends AbstractList<T> implements RandomAccess, Serializable {
final List<F> fromList;
final Function<? super F, ? extends T> function;
private static final long serialVersionUID = 0L;
TransformingRandomAccessList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = (List)Preconditions.checkNotNull(fromList);
this.function = (Function)Preconditions.checkNotNull(function);
}
public ListIterator<T> listIterator(int index) {
return new TransformedListIterator(this.fromList.listIterator(index)) {
T transform(F from) {
return TransformingRandomAccessList.this.function.apply(from);
}
};
}
}
可以看到这个listIterator实际上就是根据传入的函数对数据进行处理的,实际上就是使用者自己对List进行转型的,这个工具只不过实现了对每一个迭代的时候使用使用者传入的函数,进行输出结果。不过根据这个源码可以看到一个坑,就是他使用的引用还是传入的那个集合的引用,如果原集合出现变化,这个集合也会跟着变的。
对list进行分批输出的方法(作用之一:分页)
public static <T> List<List<T>> partition(List<T> list, int size) {
Preconditions.checkNotNull(list);
Preconditions.checkArgument(size > 0);
return (List)(list instanceof RandomAccess?new Lists.RandomAccessPartition(list, size):new Lists.Partition(list, size));
}
看源码可以知道,程序根据传入的List进行分类处理,不过RandomAccessPartition是Partition的子类,且RandomAccessPartition对其的处理是直接调用了父类的方法,所以我们只需要解析Partition类就可以了:
private static class Partition<T> extends AbstractList<List<T>> {
final List<T> list;
final int size;
Partition(List<T> list, int size) {
this.list = list;
this.size = size;
}
public List<T> get(int index) {
Preconditions.checkElementIndex(index, this.size());
int start = index * this.size;
int end = Math.min(start + this.size, this.list.size());
return this.list.subList(start, end);
}
public int size() {
return IntMath.divide(this.list.size(), this.size, RoundingMode.CEILING);
}
public boolean isEmpty() {
return this.list.isEmpty();
}
}
它的get方法进行了截取操作,而它的截取底层是subList实现的。它所get的下标为第几组List
将字符串作为字符数组进行操作
public static ImmutableList<Character> charactersOf(String string) {
return new Lists.StringAsImmutableList((String)Preconditions.checkNotNull(string));
}
public static List<Character> charactersOf(CharSequence sequence) {
return new Lists.CharSequenceAsList((CharSequence)Preconditions.checkNotNull(sequence));
}
两个方法分别接收字符串和CharSequence作为参数,将参数传入CharSequenceAsList类中进行处理:
private static final class StringAsImmutableList extends ImmutableList<Character> {
private final String string;
StringAsImmutableList(String string) {
this.string = string;
}
public int indexOf(@Nullable Object object) {
return object instanceof Character?this.string.indexOf(((Character)object).charValue()):-1;
}
public int lastIndexOf(@Nullable Object object) {
return object instanceof Character?this.string.lastIndexOf(((Character)object).charValue()):-1;
}
public ImmutableList<Character> subList(int fromIndex, int toIndex) {
Preconditions.checkPositionIndexes(fromIndex, toIndex, this.size());
return Lists.charactersOf((String)this.string.substring(fromIndex, toIndex));
}
boolean isPartialView() {
return false;
}
public Character get(int index) {
Preconditions.checkElementIndex(index, this.size());
return Character.valueOf(this.string.charAt(index));
}
public int size() {
return this.string.length();
}
}
可以看到CharSequenceAsList类的实现实际上就是对间接使用String类中的方法进行处理字符串
将list逆序
public static <T> List<T> reverse(List<T> list) {
return (List)(list instanceof ImmutableList?((ImmutableList)list).reverse():(list instanceof Lists.ReverseList?((Lists.ReverseList)list).getForwardList():(list instanceof RandomAccess?new Lists.RandomAccessReverseList(list):new Lists.ReverseList(list))));
}
可以看到这个reverse方法实际上调用了ImmutableList类的reverse方法进行处理的逆序