一、Consumer接口是什么?
在Java 8中,Consumer是一个用来接收一个对象并操作该对象而不返回结果的函数式接口。该接口包含一个操作函数接受单个泛型参数,方法是:void accept(T t),枚举类型中的forEach方法便是一个非常典型的Consumer函数接口例子,接收一个Consumer作为参数,对于枚举中的每个元素执行一些操作。
二、Consumer的使用场景
Consumer主要被广泛应用于lambda表达式或方法引用作为参数的情境下。通过传递Consumer,我们可以将一个操作应用到一个或多个值上,可以对常规操作对应的接口进行抽象。Consumer的使用可以大大简化代码,减少冗余代码。
三、Consumer接口使用示例
//打印两次hello world!
Consumer<String> consumer = s -> System.out.println(s+"hello world!");
consumer.accept("第一次-");
consumer.accept("第二次-");
运行结果为:
第一次-hello world! 第二次-hello world!
此外,我们也可以使用andThen()方法将多个Consumer组合起来。
//将两个consumer合并成一个
Consumer<String> consumer1 = s -> System.out.println("hello " + s);
Consumer<String> consumer2 = s -> System.out.println(s.toUpperCase());
consumer1.andThen(consumer2).accept("world!");
运行结果为:
hello world! WORLD!
四、Consumer进阶应用
1、使用Consumer和Stream分离关注点
在Java 8之前,对于集合数据操作,操作代码与流程代码通常是相互交织在一起的,有些难以维护。而通过函数式编程的方法,我们可以将具体操作和流程代码分离。对于集合类型的数据,我们可以利用stream流来实现这一点,通过将操作编写为一个Consumer接口的实例,再使用Stream类的forEach()方法执行操作。
//可以通过Stream遍历集合
List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
languages.stream().forEach(x -> System.out.println(x));
运行结果为:
Java Scala C++ Haskell Lisp
以上的代码可以通过foreach方法对集合进行遍历,而foreach方法接收了一个Consumer类型的参数——x -> System.out.println(x)。这里代表着在使用Stream遍历集合的过程中,需要执行的操作被定义在了Consumer中。
2、使用Consumer进行链式操作
在流操作中,我们除了使用map方法可以将集合中的每个元素都应用指定的函数之外,还可以通过flatMap方法将多个Stream流处理成一个Stream流。
//一个简单的POJO类 public class User { private Long id; private String name; private Integer age; // 省略相应的getter和setter方法 } List<User> users = Arrays.asList(new User(1L,"a",10),new User(2L,"b",20),new User(3L,"c",30)); users.stream() //只选择满足条件的年龄大于10岁的用户 .filter(user -> user.getAge() > 10) //提取出用户的名字 .map(User::getName) //对于名字为"b"的用户进行特殊处理 .peek(name -> { if (name.equals("b")) { System.out.println("name is"+name); } }) //最终进行打印 .forEach(System.out::println);
运行结果为:
a name is b b c
以上代码中,peek操作可以结合Consumer的执行操作,用于链式处理信息,对流进行副本处理。
五、小结
Java 8中的Consumer接口为我们提供了一个更加简便的无返回值的函数式接口,在其他函数式编程语言中也有类似的接口。在实际开发中,我们可以将Consumer应用于对于集合类型数据的处理中,通过lambda表达式或方法引用作为参数,从而达到极大的代码精简效果。