先了解下这个单词的意思:Consumer [kənˈsjuːmə(r)] :消费者
既然是消费者,那么它消费的是什么呢?先说结论:消费的是函数(或是代码段),封装的是逻辑代码。
先看看,如果我们要遍历一个List集合,一般我们会这么写:
List<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
for (String s : list) {
System.out.println(s);
}
那如果我要遍历list,但是我又不想写增强for遍历list呢?那我们可以把增强for提前写好,并封装到一个处理步骤中,如下:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
这个是jdk源码中的List的forEach方法,可以看到forEach方法把增强for的逻辑封装到方法体了(封装的是逻辑代码)。在这段逻辑代码中,action.accept(t);代表的是消费的函数体本身或者是我们写的任意代码(消费的是函数)
写完这个,接下来的调用就方法了,如下:
简单的遍历打印:
list.forEach(System.out::println);
或者是遍历要处理的任何逻辑:
list.forEach(a -> {
if (a.equals("aa")) {
System.out.println("找到aa了");
}
});
()->{}Lambda表达式可以写成双冒号表达式的前提是:代码片段就是函数体本身,函数的入参是箭头(->)左边的那个参数。
这里涉及到了java8的Lambda表达式,不太了解的可以参考:https://blog.youkuaiyun.com/river66/article/details/104847979
延伸拓展:
1、如果一段代码中有固定的入参类型,这段代码会在很多地方使用到,而且使用这段代码还有各种过滤条件。这时候,我们把这段代码封装为一个方法(写过滤代码),入参就定义为Consumer类型。
2、一个需要维护数据对象的类(如ArrayList底层维护的是一个数组:Object[] elementData),在封装的逻辑代码中需要使用到所维护的数据对象时,即可考虑使用Consumer为入参。