java典型接口方法_Java 常用函数式接口 —— Consumer接口

JDK提供了大量的函数式接口,方便我们开发的时候无需自己编写接口,这些接口都比较通用,学会他们并且在工作中使用,不仅方便的解决问题,而且十分优雅。

1、接口概述

Consumer 接口也比较简单,只有两个方法,一个是抽象方法,一个是默认方法:@FunctionalInterface

public interface Consumer {

void accept(T t);

default Consumer andThen(Consumer super T> after){

Objects.requireNonNull(after);

return (T t) -> { accept(t); after.accept(t); };

}

}

2、accept 方法

该方法接收一个接口泛型类型的对象,没有返回值。

看看集合的 forEach 方法的使用:public class ConsumerTest {

public static void main(String[] args) {

List names = new ArrayList() {

{

add("Tom");

add("Jerry");

}

};

names.forEach(e -> System.out.println(e));

names.forEach(System.out::println);

}

}

我们使用 forEach 方法的时候,该方法就是使用了 Consumer 接口作为参数。这是我们最常见的使用 Consumer 的方式。

除了打印信息,一般我们对于集合中的对象的某些数据需要更改,也经常使用forEach 遍历,然后对于每个对象做一些业务操作。

虽然 forEach 常用,但是一般我们都很少关注 forEach 的实现,也很少自己写个方法用到 Consumer 接口:default void forEach(Consumer super T> action) {

Objects.requireNonNull(action);

for (T t : this) {

action.accept(t);

}

}

3、Consumer接口使用场景-回调public class ConsumerTest {

private static final Map map = new HashMap() {

{

put(10, "Tom");

put(3, "Jerry");

}

};

public static void main(String[] args) {

//调用方法,同时编写对结果的回调:此处仅仅打印而已

test(3, System.out::println);

}

public static void test(Integer age, Consumer consumer) {

//业务处理

System.out.println(age);

//对处理结果的回调:下面的ifPresent参数也是Consumer接口,所有下面三种写法都可以

//Optional.ofNullable(map.get(age)).ifPresent(e -> consumer.accept(e));

//Optional.ofNullable(map.get(age)).ifPresent(consumer::accept);

Optional.ofNullable(map.get(age)).ifPresent(consumer);

}

}

Consumer 接口一般作为方法参数来实现回调的功能,例如上面的例子,test 函数传递待处理的对象 age ,经过业务处理得到其它结果对象,之后调用 accept 对结果对象进行处理。

实际中回调处理的对象是根据入参得到其它结果。比如传入姓名从数据库查询数据,回调函数将数据保存在其它地方,那么这个其它地方就需要调用者自己处理,比如存文件。

4、默认方法andThen

方法源码:default Consumer andThen(Consumer super T> after) {

Objects.requireNonNull(after);

return (T t) -> { accept(t); after.accept(t); };

}

使用场景:public static void main(String[] args) {

Consumer first = (x) -> System.out.println(x.toLowerCase());

Consumer next = (x) -> System.out.println(x.toUpperCase());

first.andThen(next).accept("Hello World");

}

andThen 接收一个 Consumer 接口,返回的也是一个 Consumer 接口,同样的,调用该方法的也是 Consumer 接口。这个地方比较绕,需要对照上面两处代码仔细分析。

first 是一个 Consumer 接口,当调用 andThen 方法的时候,并不是执行 (T t) -> { accept(t); after.accept(t); } 这段代码,而是返回了一个 Consumer 接口,注意它的结构是给一个对象 t,然后大括号中消费 t 。 处理逻辑是当前 Consumer 执行 accept 方法,然后再让 after 这个 Consumer 执行 accept 方法。理解 andThen 方法返回的结构特别重要。

当first.andThen(next)执行完成,得到一个 Consumer 接口接口后,再次调用 accept("Hello World") 时,实际上对 Hello World 字符串执行的内容就是大括号里面的内容了:accept(t); after.accept(t); 也就是上面的先输出小写字符串、再输出大写的字符串了。

5、andThen 方法使用场景public class ConsumerTest {

private static final Map> QUEUE = new ConcurrentHashMap<>();

public static void main(String[] args) {

resolve(1, s -> System.out.println(s.toUpperCase()));

resolve(1, s -> System.out.println(s.toLowerCase()));

resolve(1, s -> System.out.println(s.substring(0, 2)));

QUEUE.get(1).accept("Hello World");

}

public static void resolve(Integer id, Consumer callback) {

final Consumer existing = QUEUE.get(id);

if (callback == null) callback = i -> {};

if (existing != null && callback != existing) {

callback = existing.andThen(callback);

}

QUEUE.put(id, callback);

}

}

结果如下:HELLO WORLD

hello world

He

上面代码中的 resolve 方法根据 id , 向 map 类型的 QUEUE 中增加多个回调函数,最后执行的时候,多个回调函数都被执行,很类似责任链的设计模式。可以结合上面的讲解仔细理解callback = existing.andThen(callback);

以及在执行的地方:QUEUE.get(1).accept("Hello World");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值