在jdk8中什么是函数式接口: 1、被@FunctionalInterface注解修饰的。
2、接口里边只有一个非default的方法。 满足以上2个条件的即为函数式接口,ps:即使一个接口没有被@FunctionalInterface修饰,但是满足2,那么这样的接口也会是函数式接口。Supplier 概要:不接受参数,返回一个值。 jdk源码:
1 2 3 4 5 6 7 8 9 10 11 */ @FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
即:Supplier不接受参数,返回一个值。 example:
1 2 3 4 5 6 public class SupplierTest { public static void main(String[] args) { Supplier<Student> supplier = Student::new;//这里使用了方法引用(后续解释)生成了一个对象。 System.out.println(supplier.get().getName()); } }
Function 概要:接受一个参数返回一个值 jdk源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 //类型T入参,类型R是返回值的类型 @FunctionalInterface public interface Function<T, R> { /** 接受一个参数,返回一个结果 */ R apply(T t); /** * 默认方法是讲的课8新加入的一种类型,入参before是一个Function(接受参数V类型,输出T类型),从实现来看其首先调用before的行为得到输出T, * 随后T作为当前Function的入参,最后当前Function输入R类型。即:compose函数传入的函数首先被调用,得到的结果作为当前Function的入参使用 */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * andThen是和compose相反的操作,当前Function首先被调用,得到的结果作为参数after的入参,调用after。 */ 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; } }
BiFunction 概要:接受2个参数,返回一个值。 jdk源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 //T和U类型是参数,R类型是返回值。 @FunctionalInterface public interface BiFunction<T, U, R> { /** * BiFunction的主方法,接受2个参数,返回一个结果 */ R apply(T t, U u); /** * 先执行当前BiFunction的行为,得到结果R类型,R类型最后作为Function的实例after的入参(泛型“? super R”即“?”是R类型或者是R类型的 * 父级)返回V类型的结果。PS:考虑为什么andThen的入参是一个Function,而不是一个BiFunction? */ default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); } }
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 /** * Created by CeaserWang on 2017/1/8. */ public class FunctionATest { public static void main(String[] args) { FunctionATest functionTestA = new FunctionATest(); // functionTestA.testfunction1(); System.out.println(functionTestA.computeA(3,value -> value = value * 3,value -> value+1)); System.out.println(functionTestA.computeB(3,value -> value = value * 3,value -> value+1)); System.out.println(functionTestA.computeC(3,4,(value1,value2) -> {return value1+value2;},value -> value*value)); } public void testfunction1(){ List<String> list = Arrays.asList("zhangsan","lisi","wangwu"); Collections.sort(list,(o1,o2) -> {return o1.compareTo(o2); }); Collections.sort(list,(o1,o2) -> o1.compareTo(o2)); list.forEach((item) -> System.out.println(item)); list.forEach(String::toUpperCase); list.stream().map(String::toUpperCase).forEach(item -> System.out.println(item)); } public int computeA(int a, Function<Integer,Integer> function,Function<Integer,Integer> befor ){ return function.compose(befor).apply(a); } public int computeB(int a, Function<Integer,Integer> function,Function<Integer,Integer> after ){ return function.andThen(after).apply(a); } public int computeC(int a,int b, BiFunction<Integer, Integer,Integer> bifunction, Function<Integer,Integer> function ){ return bifunction.andThen(function).apply(a,b); } }
BinaryOperator 概要:继承了BiFunction新加了2个求最大值和最小值的方法。 jdk源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //继承了BiFunction,入参和返回值都是同一种类型T,因为2中相同类型的元素做大小比较,返回的是其中一个,即还是原来入参的类型。 @FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> { /** * 根据比较器comparator求最小值 */ public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } /** * 根据比较器comparator求最大值 */ public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } }
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 /** * Created by Administrator on 2017/1/8. */ public class BinaryOperatorTest { public static void main(String[] args) { BinaryOperatorTest BinaryOperatorTest = new BinaryOperatorTest(); Integer rnum = BinaryOperatorTest.compute(2,3,(num1,num2) -> {return num1 * num2;},value -> 2*value); System.out.println(rnum); System.out.println("-------------------------------------"); Integer rnum2 = BinaryOperatorTest.compute(2,3,(num1,num2) -> {return num1 * num2;}); System.out.println(rnum2); System.out.println("-------------------------------------"); Integer rnum3 = BinaryOperatorTest.computeA(2,3,(num1,num2) -> num1.compareTo(num2)); System.out.println(rnum3); } public Integer compute(Integer a, Integer b, BinaryOperator<Integer> binaryoperator, Function<Integer,Integer> function) { return binaryoperator.andThen(function).apply(a,b); } public Integer compute(Integer a, Integer b, BinaryOperator<Integer> binaryoperator) { return binaryoperator.apply(a,b); } public Integer computeA(Integer a, Integer b, Comparator<Integer> comparator){ return BinaryOperator.minBy(comparator).apply(a,b); } }
Predicate 概要:接受一个参数返回boolean类型,常用语filter过滤条件使用。 jdk源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 @FunctionalInterface public interface Predicate<T> { /** * 接受一个参数返回一个boolean值 */ boolean test(T t); /** *与操作,支持短路与 */ default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } /** * 取反操作 */ default Predicate<T> negate() { return (t) -> !test(t); } /** * 或操作,支持短路或 */ default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } /** * 比较2个对象是否相同 */ static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 /** * Created by CeaserWang on 2017/1/8. */ public class PredicateTest { public static void main(String[] args) { Predicate<String> mypredicate = value -> value.length()>5; System.out.println(mypredicate.test("hello55s")); List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9); PredicateTest predicatetest = new PredicateTest(); predicatetest.condationA(nums,value -> value>5); System.out.println("\n---------------------------"); predicatetest.condationA(nums,value -> value % 2 ==0); System.out.println("\n---------------------------"); System.out.println(predicatetest.condationEqual("test").test("test")); } public void condationA(List<Integer> list, Predicate<Integer> predate){ for(Integer item : list){ if(predate.test(item)){ System.out.print(item); } } } public Predicate<String> condationEqual(Object obj){ return Predicate.isEqual(obj) ; } }
Optional 概要:jdk8为了解决NPE问题提供的解决方案。 在jdk7中业务中很多代码都是这样:
1 2 3 if(null!=XXX){ doSomeThing(); }
开发人员需要警惕NPE问题,给开发带来了一些不便,现在我们不想用这三行固定的语句,为此jdk8有了Optional。 Optional内部维护了一个value的成员变量,为此Optional提供了诸多针对于此成员变量的方法。 Optional中的其中一个方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 //空对象 private static final Optional<?> EMPTY = new Optional<>(); //Optional维护的值 private final T value; //是否是空值 public boolean isPresent() { return value != null; } //如果不是空值,那么执行针对于value的行为。 public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); } //构造一个值为value的Optional对象,value不能为空,否则报错。 public static <T> Optional<T> of(T value) { return new Optional<>(value); } //返回一个空值 public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } //创建一个允许空值的Optional对象 public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 /** * Created by CeaserWang on 2017/1/8. * optional 不要作为成员变量或者参数,optional只是为了应对null异常而来的 */ public class OptionalTest { public static void main(String[] args) { OptionalTest OptionalTest = new OptionalTest(); OptionalTest.optionalA(); OptionalTest.optionalB(); } public void optionalA(){ //Optional optional = Optional.of("hello"); Optional optional = Optional.ofNullable(null);//创建一个空的对象 optional.ifPresent(item -> System.out.println(item));//如果为空此行代码不会报错。 System.out.println(optional.orElse("world"));//如果为空输出word System.out.println(optional.orElseGet(() -> "opop"));//如果为空,取Supplier提供的值 } public void optionalB(){ Company company = new Company(); Employee e1 = new Employee(); Employee e2 = new Employee(); company.setEmployyee(Arrays.asList(e1,e2)); Optional<Company> optional = Optional.ofNullable(company); System.out.println(optional.map(icompany -> icompany.getEmployyee()).orElse(Collections.emptyList())); } }
函数式编程和以往的面向对象的方式有一定的区别,函数式编程方法的参数可以传递行为,这些行为包括但不限于以上介绍的这些,jdk8提供的函数式编程的辅助类在java.util.function包下边:
这些针对于函数式编程的辅助类,对以后的收集器,流是基础,后续的jdk新加的框架都是使用这些基类展开的。
jdk8新加入的default方法 default方法的加入是为了兼容jdk8以前的版本的需要。 (1)当前有两个接口MyInterface和MyInterface1,它们都有相同名字的default方法,之后实现类Myclass同时implements了MyInterface和MyInterface1,同时Myclass实现了default方法,此时Myclass调用default调的是谁的? (2)一个接口I有一个default方法,另一个实现类A实现了了此接口,并且重写了default方法,之后另一个类B继承了实现类A并且实现了接口I,那么在这种情况下,实现类B调用的default方法又是谁的呢?针对这两种情况编写测试代码:
接口MyInterface
1 2 3 4 5 6 7 8 /** * Created by CeaserWang on 2017/1/16. */ public interface MyInterface { default void meyhod(){ System.out.println("MyInterface"); } }
接口MyInterface1
1 2 3 4 5 public interface MyInterface1 { default void meyhod(){ System.out.println("MyInterface1"); } }
实现类ExtendsClass
1 2 3 4 5 6 public class ExtendsClass implements MyInterface { public void meyhod(){ System.out.println("ExtendsClass"); } }
实现类FixClass
1 2 3 public class FixClass extends ExtendsClass implements MyInterface1 { }
测试类Myclass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Myclass implements MyInterface,MyInterface1 { public void meyhod(){ System.out.println("Myclass"); //MyInterface1.super.meyhod(); } public static void main(String[] args) { Myclass myclass = new Myclass(); myclass.meyhod(); FixClass fixClass = new FixClass(); fixClass.meyhod(); } }
运行Myclass 结果:
结论: 针对于第一种情况,default方法调用的是自身的实现的default方法。 针对于第二种情况,default方法调用的是“就近原则”,ExtendsClass 首先被实现,那么首选是ExtendsClass 的default方法,因此输出“ExtendsClass”。
jdk8-方法引用
方法引用的形式 方法引用的标准形式是:类名::方法名。(注意:只需要写方法名,不需要写括号)
有以下四种形式的方法引用:
类型 示例 引用静态方法 ContainingClass::staticMethodName 引用某个对象的实例方法 containingObject::instanceMethodName 引用某个类型的任意对象的实例方法 ContainingType::methodName 引用构造方法 ClassName::new
下面我们通过一个小Demo来分别学习这几种形式的方法引用: Student 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class Student { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } public static int coompareStudentByScore(Student student1,Student student2){ return student1.getScore() - student2.getScore(); } public static int coompareStudentByName(Student student1,Student student2){ return student1.getName().compareToIgnoreCase(student2.getName()); } public int compareScore(Student student){ return this.score-student.getScore(); } }
StudentComparator 比较器:
1 2 3 4 5 6 7 8 9 10 11 public class StudentComparator { public int coompareStudentByScore(Student student1,Student student2){ return student1.getScore() - student2.getScore(); } public int coompareStudentByName(Student student1,Student student2){ return student1.getName().compareToIgnoreCase(student2.getName()); } }
测试类:MethodReferenceTest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 * Created by CeaserWang on 2017/1/15. */ public class MethodReferenceTest { public String toString(Supplier<String> supplier){ return supplier.get()+"test"; } public String toString2(String str, Function<String,String> function){ return function.apply(str); } public static void main(String[] args) { Student student1 = new Student("zhangsan",20); Student student2 = new Student("lisi",90); Student student3 = new Student("wangwu",50); Student student4 = new Student("zhaoliu",60); List<Student> students = Arrays.asList(student1,student2,student3,student4); //lambda形式 students.sort((studentparam1,studentparam2) -> Student.coompareStudentByName(studentparam1,studentparam2)); students.forEach(student -> System.out.println(student.getName()));*/ // 引用静态方法 /* students.sort( Student::coompareStudentByName); students.forEach(student -> System.out.println(student.getName())); System.out.println("----------------------------------------------"); //引用某个对象的实例方法 StudentComparator studentComparator = new StudentComparator(); students.sort(studentComparator::coompareStudentByScore); students.forEach(student -> System.out.println(student.getScore())); System.out.println("----------------------------------------------"); //引用某个类型的任意对象的实例方法 students.sort(Student::compareScore); students.forEach(student -> System.out.println(student.getScore())); MethodReferenceTest methodReferenceTest = new MethodReferenceTest(); //引用构造方法 System.out.println( methodReferenceTest.toString(String::new)); System.out.println( methodReferenceTest.toString2("hello",String::new)); } }