个人博客项目地址
希望各位帮忙点个star,给我加个小星星:sparkles:
Guava工具包是Google推出的Java工具包,想要完整学习的话,推荐去并发编程网(ifeve)进行学习,传送门。
我们在开发过程中,会经常使用到java.util.Collections这个Java自带的工具类,Guava在这个基础上,提供了更多工具方法,而且很多是静态方法。
这篇文章记录的是自己使用Lists.tranform()方法遇到的一个小问题,如有错误请提出~~
在写代码时,经常会要与外部系统进行联调,RPC获取到基础信息列表,例如用户信息List,我们需要在自己系统中根据用户ID列表进行一些信息查询,这样我们需要从Result列表里面拿出ID列表就足够了,不需要其他字段。简单来写,直接用foreach就行了,但使用Lists.tranform这个方法 可以更加简单和简洁
举个:chestnut::
List<User> users = Lists.newArrayList(new User(1, "ceshi1"), new User(2, "ceshi2")); List<String> names = Lists.transform(users, new Function<User, String>() { @Nullable @Override public String apply(@Nullable User input) { return input.getName(); } }); 复制代码
通过Lists.tranform这个方法,就能从User列表(用户列表)中取出String列表(姓名列表)。
还是上面那个例子,取出一个新列表后,对原来的list中的name进行了修改,新列表的name同样也会修改,为什么会出现这种情况呢?先来看看Lists.tranform源码注解
/** * Returns a list that applies {@code function} to each element of {@code * fromList}. The returned list is a transformed view of {@code fromList}; * changes to {@code fromList} will be reflected in the returned list and vice * versa. 返回一个列表,该列表将{@ code函数}应用到{@ code from list}的每个元素。返回的列表是{@代码从列表}转换的视图;将fromList代码的更改将反映在返回的列表中,反之亦然 ··· **/ 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); } 复制代码
翻译了一下注解,大概意思就是,使用这个方法会 返回一个列表 ,如果对源list或者返回的list进行修改后, 会同时影响到对方 ,同样可以看该静态方法返回的是一个内部静态类对象:
private static class TransformingSequentialList<F, T> extends AbstractSequentialList<T> implements Serializable { final List<F> fromList; final Function<? super F, ? extends T> function; TransformingSequentialList(List<F> fromList, Function<? super F, ? extends T> function) { this.fromList = checkNotNull(fromList); this.function = checkNotNull(function); } @Override public ListIterator<T> listIterator(final int index) { return new TransformedListIterator<F, T>(fromList.listIterator(index)) { @Override T transform(F from) { return function.apply(from); } }; } 复制代码
可以看到最后一个方法 listIterator(列表迭代器) ,每次迭代都是从fromList中取出来的,下面放一个Debug动图,可以清楚看出,源list和新list的值,都是指向同一个内存地址, 所以无论是哪一方修改后,对方拿到的引用都是一致的,都是修改后的值 :
所以如果下次对某一方修改后,记得对方列表也会相应变化,避免使用错误的值。