今天在看ArrayList源码的时候有个方法【replaceAll(UnaryOperator<E> operator)】不是很理解。主要是对于参数的不是很理解,毫不自愧的说,“第一次见”!见方法名之其意:不就是替换吗。跟字符串替换方法名字一样嘛,有啥区别嘛。但是一写测试类,就无法下手了,这参数,到底传什么嘛,几十脸懵逼。不过经过一番跟进相关类及相关方法。终于理清楚了。如有不足或错误的地方,欢迎指出~~~谢谢了。
1、关于ArrayList类中的源码:
@Override
@SuppressWarnings("unchecked")
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final int expectedModCount = modCount; //modCount表示list结构上被修改的次数
final int size = this.size; //集合长度
for (int i=0; modCount == expectedModCount && i < size; i++) {
elementData[i] = operator.apply((E) elementData[i]);
}
if (modCount != expectedModCount) { //如果集合在遍历过程中,被修改过,就报异常
throw new ConcurrentModificationException();
}
modCount++;
}
是不是一脸懵逼,没任何解释。没关系,既然是复写父类方法,经过查看父类,在List类中找到了此方法
如下:
/**
* 【源码注释很长,就不贴出来了,有兴趣的可以自己去看看。这里就简单解释下】
* 源码解释:方法用于将此列表的每个元素替换为将运算符应用于该元素的结果。操作员抛出的错误或运行时异常被转发给调用者
* 本人解释:用函数接口的返回结果替代原list中的值.
* 如果list的迭代器不支持set操作,当替换第一个元素时,会抛出异常.
*/
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
2、来看下 UnaryOperator<E> 类
/**
* 表示对单个操作数的操作,该操作数生成与其操作数类型相同的结果。
* 这个接口定义了一个静态方法,返回泛型对象的本身;
* @param <T>
*/
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
* 总是返回参数类型
* @param <T> the type of the input and output of the operator
* 输入的类型输出给操作者
* @return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
3、UnaryOperator<T>继承于Function<T, T>,我们再来看看Function<T, T>类
/**
* Function接口定义中有两个泛型,按着接口文档说明第一个泛型是输入类型,第二泛型是结果类型
*/
@FunctionalInterface
public interface Function<T, R> {
/**
* apply是一个抽象类,接收一个泛型T对象,并且返回泛型R对象
*/
R apply(T t);
/**
* compose方法接收一个Function参数before,该方法说明是返回一个组合的函数,首先会应用before,然后应用当前对象,换句话说就是先执行before对象的apply,再执行当前对象的apply,将两个执行逻辑串起来。
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* andThen方法接收一个Function参数after,与compose方法相反,它是先执行当前对象的apply方法,再执行after对象的方法。
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
3、很简单明了了,那怎么用,接下来一起来看看
List<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhaoer");
list.add("xiaozhu");
list.add("xiaoming");
list.add("xiaoliu");
list.replaceAll(a->a);
list.forEach(i->System.out.print(i+" "));
输出:zhangsan lisi wangwu zhaoer xiaozhu xiaoming xiaoliu
list.replaceAll(a->a); 这句的意思是:返回自己本身,就是用自己替换自己
如果我们想用另一个字符串替换指定的字符串呢。比如,把张三替换成张三。很简单,可以这样
list.replaceAll(a->a.equals("zhangsan")?"张三":a);
或者
list.replaceAll(a->{
if(a.equals("zhangsan"))
return "张三";
else return a;
});