ArrayList 中 replaceAll(UnaryOperator operator) 方法的作用【jdk源码分析】

今天在看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;
}); 

猜你喜欢

转载自blog.csdn.net/weixin_40841731/article/details/85288714