[六] 函数式接口的复合方法示例 predicate 谓词逻辑运算 Function接口 组合运算 比较器 逆序 比较链
复合的方法
有些函数式接口提供了允许复合的方法
也就是可以将Lambda表达式复合成为一个更加复杂的方法
之前的章节中有说到:
接口中的compose, andThen, and, or, negate 用来组合函数接口而得到更强大的函数接口
另外还有比较器中的reversed thenComparing可以用于组合运算
这几个方法分别位于Function以及Predicate中
方法示例
组合方法 andThen compose
分别计算输入初始值1,2 在四个不同的函数里面的结果
Function<Integer, Integer> f = x -> x + 2; Function<Integer, Integer> g = x -> x * 4; Function<Integer, Integer> fAndThenG = f.andThen(g); for(int i = 1;i<3;i++){ System.out.println(fAndThenG.apply(i)); } System.out.println("--------------"); Function<Integer, Integer> gAndThenF = g.andThen(f); for(int i = 1;i<3;i++){ System.out.println(gAndThenF.apply(i)); } System.out.println("--------------"); Function<Integer, Integer> fComposeG = f.compose(g);
for(int i = 1;i<3;i++){ System.out.println(fComposeG.apply(i)); } System.out.println("--------------"); Function<Integer, Integer> gComposeF = g.compose(f);
for(int i = 1;i<3;i++){ System.out.println(gComposeF.apply(i)); }
初始值为1,2 f (x)= x -> x + 2; g(x) = x -> x * 4; |
复合后: f(g(x)) = (x * 4)+2 g(f(x)) = (x+2)*4 |
结果分别是 6,10 12,16
|
再看一下打印结果信息
andThen表示 接着进行下一步运算,也就是结果进入到下一个函数中
调用者第一个函数的结果作为被调用者第二个函数的参数
也就是
第二个函数(第一个函数结果) g(f(x)) 的形式
compose 表示组合组成的含义 表示 由谁组成 也就是调用者函数由被调用者函数组成
也就是
第一个函数(第二个函数 结果) f(g(x)) 的形式
显然 对于固定的两个函数 f g
调用与被调用的顺序 和 方法的选择这两者
只能组合出来两种 f(g(x)) 或者 g(f(x))
注意,此处为了更便于表达使用了数学函数的样式展现,但是 Function意味着 输入转换为输出 不要有思维局限性认为就是为了处理数学问题
and, or, negate 与 或 非
与或非 和我们平时理解的概念并无二致 就是执行逻辑运算
and和or方法是按照在表达式链中的位置,从左向右确定优先级的。因此,a.or(b).and(c)可以看作(a || b) && c
class Stu{ private String name; private String sex; private Integer age; public Stu(){ } public Stu(String name,String sex,Integer age){ this.name = name; this.sex = sex; this.age = age; } //此处省略了 getter setter方法 @Override public String toString() { final StringBuilder sb = new StringBuilder("Stu{"); sb.append("name='").append(name).append('\''); sb.append(", sex='").append(sex).append('\''); sb.append(", age=").append(age); sb.append('}'); return sb.toString(); } }
主函数中的测试代码(省略主函数与测试类)
List<Stu> stuList = new ArrayList(){ { add(new Stu("Stu1","男",15)); add(new Stu("Stu2","女",18)); add(new Stu("Stu3","男",13)); add(new Stu("Stu4","男",28)); add(new Stu("Stu5","女",58)); add(new Stu("Stu6","女",18)); add(new Stu("Stu7","女",30)); add(new Stu("Stu8","男",6)); } }; System.out.println( stuList.stream().filter(i->i.getSex().equals("男")).filter(i->i.getAge().compareTo(18)>0).collect(Collectors.toList()) ); Predicate<Stu> checkSex = i->i.getSex().equals("男"); Predicate<Stu> checkAge = i->i.getAge().compareTo(18)>0; System.out.println( stuList.stream().filter(checkSex.and(checkAge)).collect(Collectors.toList()) ); System.out.println( stuList.stream().filter(checkSex.negate()).collect(Collectors.toList()) );
使用逻辑运算,描述更加清晰,更好理解,更符合声明式编程的思想
可以将多个不同的条件进行组合,灵活性更高
比较器方法
Stream中有 sorted方法
方法的参数正是一个Comparator,提供了
逆序 reversed
和
比较器链thenComparing (还有基本类型特化方法)
List<Stu> stuList = new ArrayList(){ { add(new Stu("Stu1","男",15)); add(new Stu("Stu2","女",18)); add(new Stu("Stu3","男",13)); add(new Stu("Stu4","男",28)); add(new Stu("Stu5","女",58)); } }; Comparator<Stu> cName = Comparator.comparing(Stu::getName); Comparator<Stu> cSex = Comparator.comparing(Stu::getSex); Comparator<Stu> cAge = Comparator.comparing(Stu::getAge); System.out.println( stuList.stream().sorted(cName).collect(Collectors.toList()) ); System.out.println( stuList.stream().sorted(cName.reversed()).collect(Collectors.toList()) ); System.out.println( stuList.stream().sorted(cSex).collect(Collectors.toList()) ); System.out.println( stuList.stream().sorted(cSex.thenComparing(cAge)).collect(Collectors.toList()) );
从结果可以看得出来
第一组按照姓名升序
第二组按照姓名降序
第三组按照性别排序,但是年龄没有排序
第四组按照性别排序,同性别的按照年龄排序