编程技巧之Consumer的运用

java8开始,提供了函数式编程的功能,相关的接口有Consumer,Function等等.
我们先看一下Consumer的接口

void accept(T t);
//
default Consumer<T> andThen(Consumer<? super T> after) {
     Objects.requireNonNull(after);
     return (T t) -> { accept(t); after.accept(t); };
}

如何使用?
假设我们有一个简单的需求,我们要把一个数组给打印出来

  public static void print(List<Integer> list) {
           System.out.println(list);
    }

过了一段时间,产品又提了个新需求,需要用分号把数组隔开,之前的功能还要保留.于是你又得写一个方法.

  public static void print(List<Integer> list) {
        String s = Joiner.on("-").join(list);
        System.out.println(s);
    }

如果产品又提了个需求,需要用*号隔开呢?

  public static void print(List<Integer> list) {
        String s = Joiner.on("*").join(list);
        System.out.println(s);
    }

如果又来一个需求呢?需要把这些打印好的数组发给第三方,那么是不是又得改代码呢?
其实本质的问题是,我们没有把变化封装出来,抽象的不够.
那么该怎么修改呢?我们就要用到Consumer了.
我们先实现一个打印的方法.这个方法可以不做任何事.只是提供出来调用.

  public static void print(Consumer<List<Integer>> consumer,List<Integer> list) {
        consumer.accept(list);
    }

这个方法没有任何的业务逻辑,当你需要调用的时候,你传一个lambada进来,你就可以自定义实现.

 static Consumer<List<Integer>> printRaw = System.out::println;
 static Consumer<List<Integer>> printWithDot = list -> {
        String s = Joiner.on("-").join(list);
        System.out.println(s);
    };

    print(printRaw, Arrays.asList(1, 2, 3, 4, 5));
    print(printWithDot, Arrays.asList(1, 2, 3, 4, 5));

这样不管你需求再这么变化,print这个元方法都无需任何改变,因为变化的点已经被我们提取出来了.因为java的方法是无法作为参数传入到另一个方法的,所有lambada就发挥作用了.这个只是一个简单的demo.我们看看工程里是如何实现的.

forEach

其实跟上面的demo很像,你可以自定义如何forEach.

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

那map其实也是一样,只是Consumer接受参数处理,是无需返回的.map的参数是一个Function,把A映射到B然后返回B.

 R apply(T t);

然后我们想想,我们用map的时候,是不是万物皆可映射.我们慢慢的体会下吧.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容