java函数式编程的类主要定义在java.util.function包下。快速浏览了下该包下的一些类和接口。读者要想看懂function相关的源码,也需要对lambda表达式和泛型有一定的了解。本文只讲function包下的一些源码解析
Predicate接口
Predicate在java函数式编程中起到了过滤的作用。java 8函数编程引入了Stream类。该类配合function包下定义的一些接口,实现了一系列的函数式编程方法。 比如Stream类的过滤功能
过滤一些符合条件的数据 Stream<T> filter(Predicate<? super T> predicate);
//函数式编程的注解 @FunctionalInterface public interface Predicate<T> { //判断t是否符合条件 //例如判断一个数是否奇数 return t % 2 != 0 boolean test(T t); //这个是接口的一个默认实现的方法表示两个Predicate之间是与的关系 //例如Predicate<Integer> isOdd 表示筛选出奇数 //Predicate<Integer> biggerThan10 表示筛选出大于10的数 //Predicate<Integer> and = isOdd.and(biggerThan10)表示大于10的奇数 default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); //上面lambda等价于 //final Predicate self = this; //return new Predicate<T>(){ // boolean test(T t){ // retun self.test(t) && other.test(t) // } //} } //求反Predicate<T> isEven = isOdd.negate()表示筛选出偶数 default Predicate<T> negate() { return (t) -> !test(t); } //或的关系,用and的例子来讲 isOdd.or(biggerThan10)表示大于10或者是奇数的数 default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } }
下面我们结合一个例子来了解下Predicate的原始用法(结合Stream使用才叫高级用法)
给定一个集合{1,2,3,4,5,6,7,8,9,10}我们要找出其中的奇数。结合Predicate我们可以这样实现
Predicate<Integer> p = new Predicate<Integer>(){ public boolean test(Integer o){ return o % 2 != 0; } }; Integer[] arr = {1,2,3,4,5,6,7,8,9,10}; for(Integer i:arr){ if(p.test(i)){ System.out.print(i);//输出13579 } } 用lambda Predicate<Integer> p = o-> o % 2 != 0; Integer[] arr = {1,2,3,4,5,6,7,8,9,10}; for(Integer i:arr){ if(p.test(i)){ System.out.println(i); } } 用Stream IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .filter(i -> i % 2 != 0) .forEach(i -> System.out.print(i));//输出13579
Consumer接口
public interface Consumer<T> { //根据传入的参数做出操作 void accept(T t); //做完一个操作 接着做另一个操作 default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
andThen等价于
default Consumer<T> andThen(final Consumer<? super T> after) { Objects.requireNonNull(after); final Consumer<T> self = this; return new Consumer<T>() { @Override public void accept(T t) { self.accept(t) && after.accept(t); } } }
举个例子
Consumer<Integer> c1 = new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } }; Consumer<Integer> c2 = new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer*integer); } }; c1.andThen(c2).accept(2);// 结果 2 4
主要用在Stream的forEach中
void forEach(Consumer<? super T> action);
Function接口
Fuction
@FunctionalInterface public interface Function<T, R> { //从T类型转换到R类型 R apply(T t); //组合最终返回的是V->R的转换。首先是V->T 然后T->R的转换 default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } //先转换T->R然后转换R->V最终返回的是T->V 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; } }
举例说明 将数字转换成相应的英文单词
Map<Integer, String> map = new HashMap<>(); map.put(1, "one"); map.put(2, "two"); map.put(3, "three"); map.put(4, "four"); map.put(5, "five"); Function<Integer, String> function = new Function<Integer, String>() { @Override public String apply(Integer integer) { return map.get(integer); } }; Consumer<String> consumer = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }; consumer.accept(function.apply(1));//结果 one
如果要获取数字对应的英文单词的字母个数呢
Function<Integer, String> getLetter = new Function<Integer, String>() { @Override public String apply(Integer integer) { return map.get(integer); } }; Function<String, Integer> getLetterLength = new Function<String, Integer>() { @Override public Integer apply(String letter) { return letter.length(); } }; Consumer<Integer> consumer = new Consumer<Integer>() { @Override public void accept(Integer s) { System.out.println(s); } }; consumer.accept(getLetter.andThen(getLetterLength).apply(1));//结果3
lambda表达式
Consumer<Integer> consumer = System.out::print; Function<Integer, String> getLetter = i->map.get(i); Function<String, Integer> getLetterLength = s->s.length(); Function<Integer, Integer> indexAndSize = getLetter.andThen(getLetterLength); consumer.accept(indexAndSize.apply(1));
Stream中使用
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
用Stream实现一个简单的例子
打印从0到10 偶数对应的英文单词
Map<Integer, String> map = new HashMap<>(); map.put(0, "zero"); map.put(1, "one"); map.put(2, "two"); map.put(3, "three"); map.put(4, "four"); map.put(5, "five"); map.put(6, "six"); map.put(7, "seven"); map.put(8, "eight"); map.put(9, "nine"); Stream<Integer> stream = Stream.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9); stream.filter(i -> i % 2 == 0) .map(i -> map.get(i)) .forEach(s -> System.out.println(s)); 结果 zero two four six eight