0%

ArrayList-replaceAll方法总结

前言:因为这个方法是java8新增,稍复杂,所以单独讲

replaceAll方法

replaceAll是Java8新增方法,作用是用函数接口的返回结果替代原list中的值

参数是UnaryOperator,也就是一元操作符的意思,也就是函数式接口(函数式接口可以简化为lambda表达式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
@SuppressWarnings("unchecked")
public void replaceAll(UnaryOperator<E> operator) {
// 判断对象是否为空
Objects.requireNonNull(operator);
// 用于检测并发修改
final int expectedModCount = modCount;
// 将集合数据根据apply转换
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
elementData[i] = operator.apply((E) elementData[i]);
}
// 检测到对象的并发修改,但 replaceAll不允许,抛出此异常。
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
// 结构性修改+1
modCount++;
}

UnaryOperator接口

UnaryOperator接口继承了Function接口,接口中只有一个非常简单的静态方法

1
2
3
4
5
6
7
8
9
10
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Java8接口可以有静态方法
* 表示对单个操作数的操作,该操作数生成与其操作数类型相同的结果
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}

Function

查看一下Function接口的源码,核心是apply方法,compose、 andThen方法则是对apply的增强,举个例子,apply方法就是一个f(x)函数,输入x,返回y,compose、andThen则是f(g(x))、g(f(x)),实现了函数组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@FunctionalInterface
public interface Function<T, R> {
// 泛型方法,T是参数,R是结果,具体的操作取决于传入的lambda表达式。
R apply(T t);

/**
* 这是Java8新增的默认方法,默认方法就是接口可以有实现的方法
* compose方法接收一个Function参数before,返回Function结果(<V>是泛型标识)
* 递归,先调用参数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参数before,返回Function结果
* 递归,先执行当前对象的apply,再调用参数after的apply方法
*/
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;
}
}

例子

两个简单实例,第一个,存放手机号,正常输出是输出整个字符串,现在需要脱敏,可以使用replaceAll方法,用自己规定的函数接口的返回结果替代list中的值

1
2
3
4
5
6
7
8
9
10
11
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("18667011342");
list.add("13212345678");
list.add("13530789782");
list.add("13724058459");
list.replaceAll(s -> s.substring(0, 3) + "****" + s.substring(7));
list.forEach(System.out::println);
}
}

运行结果

image-20200102002049360

第二个,list中存放了数字,要求输出1到该数字的和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author shency
* @description: TODO
* @date: 2019/12/5
*/
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(5);
list.add(10);
list.replaceAll(num -> {
int sum = 0;
for (int i = 1; i <= num; i++) {
sum += i;
}
return sum;
});
list.forEach(System.out::println);
}
}
-------------本文结束感谢您的阅读-------------