本文主要內容:
一、guava中Lists使用場景
reverse()方法的使用場景如下,返回[3, 2, 1] (一個list)
Lists.reverse(Arrays.asList(1, 2, 3))
partition方法的使用場景如下,返回[[1, 2, 3], [4, 5]] (一個list)
Lists.partition(Arrays.asList(1, 2, 3,4,5),3)
transform()方法使用場景如下,結果爲[4, 2, 3] (一個list)
List<String> list = Lists.newArrayList("我在閱讀","源碼","很開心");
System.out.println(Lists.transform(list, e->e.length()));//返回list中每個元素的長度的list
二、源碼分析(guava中好喜歡用靜態內部類啊啊)
①Reverse方法,真的要把一個list reverse一下嗎?
reverse方法方法並不是真的把list reverse一下,返回的reverseList的底層原理是原List支持,只是取了反轉後的位置元素而已,所以,對原先的List的改變會導致reverseList也跟着改變,其中傳進來的List有四種類型情況:
public static <T> List<T> reverse(List<T> list) {
if (list instanceof ImmutableList) {
//如果是ImmutableList類型,則調用該類型list的reverse()方法獲得reversed的list
return ((ImmutableList<T>) list).reverse();
} else if (list instanceof ReverseList) {
//如果是ReverseList<T>類型,之間返回它的內部成員變量forwardList
return ((ReverseList<T>) list).getForwardList();
} else if (list instanceof RandomAccess) {
//如果指定的list是RandomAccess類型的,返回的list也是random-access的,其中 RandomAccessReverseList<T>也是Lists中的靜態內部類,繼承自ReverseList<T>類
return new RandomAccessReverseList<>(list);
} else {
//返回ReverseList<>類型,list的參數會被賦值給ReverseList的成員變量private final List<T> forwardList;
return new ReverseList<>(list);
}
}
ReverseList是Lists的靜態內部類,它繼承自AbstractList抽象List接口,在ReverseList中有個與自己逆向的forwardList類型
private static class ReverseList<T> extends AbstractList<T> {
private final List<T> forwardList;
...
//由原先的index計算出逆轉後對應的index, 如0123,第一個位置index爲0,逆轉後爲(size-1)-index=(4-1)-0=3,所以逆轉list對應index爲3
private int reverseIndex(int index) {
int size = size();
checkElementIndex(index, size);
return (size - 1) - index;
}
//reversePosition和上面原理類似,主要用於出入刪除元素位置
private int reversePosition(int index) {
int size = size();
checkPositionIndex(index, size);
return size - index;
}
//後面是一些AbstractList中方法的實現,包括迭代器等
...
}
②partition方法
partition方法返回連續的subList即子list,每一個子list長度 一樣,內部通過list.subList(start, end)實現但最後一個list可能長度不夠小一點,輸出的List是不可改變的,但是原list的最新狀態映射。其中Partition<>是一個繼承自AbstractList<List>的靜態內部類(又是靜態內部類!!!),RandomAccessPartition在Partition基礎上多實現了RandomAccess接口而已
public static <T> List<List<T>> partition(List<T> list, int size) {
checkNotNull(list);
checkArgument(size > 0);
return (list instanceof RandomAccess)
? new RandomAccessPartition<>(list, size)
: new Partition<>(list, size);
}
private static class Partition<T> extends AbstractList<List<T>> {
final List<T> list;//需要切分的list
final int size;//每個字list的大小
Partition(List<T> list, int size) {
this.list = list;
this.size = size;
}
@Override
public List<T> get(int index) {
checkElementIndex(index, size());//檢查邊界
int start = index * size;//去第n個list,則開始下標爲n*size
int end = Math.min(start + size, list.size());//所取list的end下標
return list.subList(start, end);//通過sublist方法取list的子list
}
@Override
public int size() {
//真個list分爲幾個子list,向上取整
return IntMath.divide(list.size(), size, RoundingMode.CEILING);
}
...
}
③transform,將集合裏每個對象轉換完然後再填入一個新的list嗎?
TransformingSequentialList<F, T>是一個繼承自AbstractSequentialList並實現了序列化接口的靜態內部類,它有兩個成員常量,一個是待轉化的原始list,一個是Function<? super F, ? extends T> function函數式接口,作用是通過迭代,運用function中的apply函數把list中的每個元素轉爲需要轉化成的元素,因此只是改了迭代方法,並沒有轉化後填入一個新的list。需要重寫函數式接口Function中的apply方法,在此學習借鑑了Function接口的用法精髓
public static <F, T> List<T> transform(
List<F> fromList, Function<? super F, ? extends T> function) {
return (fromList instanceof RandomAccess)
? new TransformingRandomAccessList<>(fromList, function)
: new TransformingSequentialList<>(fromList, function);
}
private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T>
implements Serializable {
final List<F> fromList;//待轉化的List
final Function<? super F, ? extends T> function;//函數式接口Function
TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) {
this.fromList = checkNotNull(fromList);//檢查null
this.function = checkNotNull(function);//檢查null
}
/**
* The default implementation inherited is based on iteration and removal of each element which
* can be overkill. That's why we forward this call directly to the backing list.
*/
@Override
public void clear() {
fromList.clear();
}
@Override
public int size() {
return fromList.size();//轉化後的list的size和原理的List一樣
}
@Override
public ListIterator<T> listIterator(final int index) {
//在迭代方法中通過apply方法轉化元素
return new TransformedListIterator<F, T>(fromList.listIterator(index)) {
@Override
T transform(F from) {
return function.apply(from);
}
};
}
@Override
public boolean removeIf(Predicate<? super T> filter) {
checkNotNull(filter);
//評估條件是否成立,成立則刪掉該元素,函數式接口Predicate的運用
return fromList.removeIf(element -> filter.test(function.apply(element)));
}
private static final long serialVersionUID = 0;
}