目录
1. 什么是函数式接口
函数式接口
A functional interface is any interface that contains only one abstract method. (A functional interface may contain one or more default methods or static methods.) Because a functional interface contains only one abstract method, you can omit the name of that method when you implement it.函数式接口是仅包含一种抽象方法的任何接口。 (一个函数式接口可能包含一个或多个默认方法或静态方法。)由于一个函数式接口仅包含一个抽象方法,因此在实现该方法时可以省略该方法的名称。
示例
public interface Hello {void sayHello ( String name );static void show (){}default void print (){}private void test (){}}
JDK8 专门为函数式接口提供了一个注解标识
@FunctionalInterface
,该注解只能使用在接口类型的定义上,表明这是一个函数式接口,
编译器在编译时就是会对该接口进行检测:接口中是否只有一个抽
象接口方法。如果有多个抽象接口方法或者一个抽象接口方法也没有,则将报编译错误
示例
@FunctionalInterfacepublic interface Hello {void sayHello ( String name );static void show (){}default void print (){}private void test (){}}
注意:
如果接口类型上没有
@FunctionalInterface
注解,但接口中只有一个抽象方法,这个接口也
是函数式接口。这与
@Override
注解一样,即使方法上面没有写,同样是属于方法重写
2. 函数式编程
函数式编程是一种编程方式,在 Java
中,简单来说就是一个变量能够存储一个函数。而能够实现这种赋值操作的只有 Lambda
表达式
示例
@FunctionalInterfacepublic interface Hello {void sayHello ( String name );static void show (){}default void print (){}// private void test(){}}package com . wq . functional ;public class HelloTest {public static void main ( String [] args ) {// Hello hello = name -> System.out.println(name);Hello hello = System . out :: println ;hello . sayHello ( "Marry" );}}
3. Lambda 表达式延迟执行
应用场景
在某种条件下才会处理数据
示例
package com . wq . lambda . lazy ;public interface MsgBuilder {String buildMsg ( String ... infos );}package com . wq . lambda . lazy ;public class PrintUtil {public static void print ( boolean valid , String msg ){if ( valid ){System . out . println ( msg );}}private static String build ( String ... infos ){StringBuilder builder = new StringBuilder ();for ( String info : infos ){builder . append ( info );}return builder . toString ();}public static void print ( boolean valid , String ... infos ){if ( valid ){// MsgBuilder builder = new MsgBuilder() {// @Override// public String buildMsg(String... infos) {// return PrintUtil.build(infos);// }// };// MsgBuilder builder = (String... arr) -> {// return PrintUtil.build(arr);// };// MsgBuilder builder = arr -> PrintUtil.build(arr);MsgBuilder builder = PrintUtil :: build ;System . out . println ( builder . buildMsg ( infos ));}}}package com . wq . lambda . lazy ;public class PrintTest {public static void main ( String [] args ) {String name = "Marry" ;String desc = " is friendly" ;//不会打印任何信息,但是此时已经完成了字符串的组装,这是属于性能上的浪费PrintUtil . print ( false , name + desc );//不会打印任何信息,但是也未构建字符串PrintUtil . print ( false , name , desc );//会打印信息时才会构建字符串PrintUtil . print ( true , name , desc );}}
4. Consumer 接口
void accept ( T t ); // 接收一个被消费的数据
解释说明
Consumer 顾名思义就是消费者的意思。可以消费一个被接收到的数据,至于如何消费,就需要看这个接口被如何实现。
示例
package com . wq . consumer ;import java . util . Arrays ;import java . util . HashSet ;import java . util . List ;import java . util . Set ;import java . util . function . Consumer ;public class ConsumerTest {public static void main ( String [] args ) {// Consumer<String> c1 = new Consumer<String>() {// @Override// public void accept(String s) {// System.out.println(s);// }// };// Consumer<String> c1 = (String s) -> {// System.out.println(s);// };// Consumer<String> c1 = s -> System.out.println(s);Consumer < String > c1 = System . out :: println ;c1 . accept ( " 这是被消费的信息 " );// Consumer<String> c2 = new Consumer<String>() {// @Override// public void accept(String s) {// System.out.println(s.charAt(0));// }// };Consumer < String > c2 = s -> System . out . println ( s . charAt ( 0 ));c2 . accept ( "This is a consumer" );Consumer < String > c3 = c1 . andThen ( c2 );c3 . accept ( " 先打印再取第一个字符 " );//将数组转换为集合List < Integer > numbers = Arrays . asList ( 1 , 2 , 3 , 4 , 5 );// numbers.forEach(new Consumer<Integer>() {// @Override// public void accept(Integer integer) {// System.out.println(integer);// }// });//// numbers.forEach(integer -> System.out.println(integer));numbers . forEach ( System . out :: println );Set < String > names = new HashSet <> ();names . add ( "admin" );names . add ( "test" );names . add ( "developer" );// names.forEach(new Consumer<String>() {// @Override// public void accept(String s) {// System.out.println(s);// }// });names . forEach ( System . out :: println );}}
5. BiConsumer 接口
void accept ( T t , U u ); // 接收两个被消费的数据
解释说明
BiConsumer 也是一个消费者,只是这个消费者可以一次性消费两个数据(一般是键值对)。至于如何消费,就需要看这个接口被如何实现。
示例
package com . wq . consumer ;import java . util . HashMap ;import java . util . Map ;import java . util . function . BiConsumer ;public class BiConsumerTest {public static void main ( String [] args ) {// BiConsumer<String,Integer> bc = new BiConsumer<String, Integer>() {// @Override// public void accept(String s, Integer integer) {// System.out.println(s + "=>" + integer);// }// };BiConsumer < String , Integer > bc = ( s , i ) -> System . out . println ( s + "=>" + i );bc . accept ( "a" , 1 );Map < String , String > counties = new HashMap <> ();counties . put ( "CN" , " 中国 " );counties . put ( "EN" , " 英国 " );counties . put ( "US" , " 美国 " );// counties.forEach(new BiConsumer<String, String>() {// @Override// public void accept(String s1, String s2) {// System.out.println(s1 + "=>" + s2);// }// });counties . forEach (( s1 , s2 ) -> System . out . println ( s1 + "=>" + s2 ));}}
6. Predicate 接口
boolean test ( T t ); // 检测是否满足条件default Predicate < T > and ( Predicate <? super T > other ); // 条件之间的逻辑与衔接default Predicate < T > negate (); // 条件取反default Predicate < T > or ( Predicate <? super T > other ); // 条件之间的逻辑或衔接
解释说明
Predicate 是条件的意思,可以检测给定数据是否满足条件,也可以与其他条件进行衔接。至于如何检测,就需要看这个接口被如何实现。
示例
import java . util . function . Predicate ;public class PredicateTest {public static void main ( String [] args ) {// Predicate<String> p1 = new Predicate<String>() {// @Override// public boolean test(String s) {// return s.contains("中国");// }// };Predicate < String > p1 = s -> s . contains ( " 中 " );boolean result1 = p1 . test ( " 中华人民共和国 " );System . out . println ( result1 );Predicate < String > p2 = s -> s . indexOf ( " 啊 " ) > 0 ;boolean result2 = p2 . test ( " 中华人民共和国 " );System . out . println ( result2 );Predicate < String > p3 = p1 . negate (); // 取反System . out . println ( p3 . test ( " 中华人民共和国 " ));Predicate < String > p4 = p1 . and ( p2 ); // 逻辑与衔接System . out . println ( p4 . test ( " 中华人民共和国 " ));Predicate < String > p5 = p1 . or ( p2 ); // 逻辑或衔接System . out . println ( p5 . test ( " 中华人民共和国 " ));}}
练习
学生有姓名、性别和年龄。现有一个集合内存储有10
名学生信息,请找出其中性别为男,年龄在
20
岁以上的学生,并在控制台进行输出
package com . wq . predicate ;public class Student {private String name ;private String sex ;private int age ;public Student ( String name , String sex , int age ) {this . name = name ;this . sex = sex ;this . age = age ;}public String getName () {return name ;}public void setName ( String name ) {this . name = name ;}public String getSex () {return sex ;}public void setSex ( String sex ) {this . sex = sex ;}public int getAge () {return age ;}public void setAge ( int age ) {this . age = age ;}@Overridepublic String toString () {return "Student{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", age=" + age +'}' ;}}package com . wq . predicate ;import java . util . Arrays ;import java . util . List ;import java . util . function . Consumer ;import java . util . function . Predicate ;public class Exercise {public static void main ( String [] args ) {List < Integer > numbers = Arrays . asList ( 1 , 2 , 3 , 4 , 5 );List < Student > students = Arrays . asList (new Student ( " 管理员 1" , " 男 " , 20 ),new Student ( " 管理员 2" , " 女 " , 21 ),new Student ( " 管理员 3" , " 男 " , 22 ),new Student ( " 管理员 4" , " 女 " , 23 ),new Student ( " 管理员 5" , " 男 " , 24 ),new Student ( " 管理员 6" , " 女 " , 18 ),new Student ( " 管理员 7" , " 男 " , 16 ),new Student ( " 管理员 8" , " 女 " , 19 ),new Student ( " 管理员 9" , " 男 " , 20 ),new Student ( " 管理员 0" , " 女 " , 23 ));// Predicate<Student> p1 = new Predicate<Student>() {// @Override// public boolean test(Student student) {// return "男".equals(student.getSex());// }// };Predicate < Student > p1 = stu -> " 男 " . equals ( stu . getSex ());Predicate < Student > p2 = stu -> stu . getAge () > 20 ;Predicate < Student > p3 = p1 . and ( p2 );// students.forEach(new Consumer<Student>() {// @Override// public void accept(Student student) {// if(p3.test(student)){// System.out.println(student);// }// }// });students . forEach ( student -> {if ( p3 . test ( student )){System . out . println ( student );}});}}
7. Function 接口
R apply ( T t ); // 将一个对象转换为另一种数据类型的对象default < V > Function < T , V > andThen ( Function <? super R , ? extends V >after ); // 复合转换
解释说明
Function 是功能的意思,可以将一种数据类型的对象转换为另一种数据类型的对象,至于如何转换,就需要看这个接口被如何实现。
示例
import java . util . function . Function ;public class FunctionTest {public static void main ( String [] args ) {// Function<String,Integer> f1 = new Function<String, Integer>() {// @Override// public Integer apply(String s) {// return Integer.parseInt(s);// }// };// Function<String,Integer> f1 = s -> Integer.parseInt(s);Function < String , Integer > f1 = Integer :: parseInt ;Integer i = f1 . apply ( "123" );System . out . println ( i );// Function<Integer,Double> f2 = new Function<Integer, Double>() {// @Override// public Double apply(Integer integer) {// return integer * 10.0;// }// };Function < Integer , Double > f2 = integer -> integer * 10.0 ;System . out . println ( f2 . apply ( i ));Function < String , Double > f3 = f1 . andThen ( f2 );double d = f3 . apply ( "5" );System . out . println ( d );}}
练习
现有文本存储学生信息如下:
谢霆锋 , 男 ,37刘德华 , 男 ,52郭富城 , 男 ,46张学友 , 男 ,40
要求将学生信息从文本中读取出来并转换为学生对象,然后存储在集合中
import java . io . BufferedReader ;import java . io . FileNotFoundException ;import java . io . FileReader ;import java . io . IOException ;import java . util . ArrayList ;import java . util . List ;import java . util . function . Function ;public class Exercise {public static void main ( String [] args ) {String path = "F:/stu.txt" ;// Function<String, Student> function = new Function<String, Student>() {// @Override// public Student apply(String s) {// return new Student(s.split(","));// }// };Function < String , Student > function = s -> newStudent ( s . split ( "," ));List < Student > students = readStudent ( path , function );students . forEach ( System . out :: println );System . out . println ( "========================" );// Function<String[], Student> f = new Function<String[], Student> () {// @Override// public Student apply(String[] strings) {// return new Student(strings);// }// };// Function<String[], Student> f = strings -> new Student(strings);Function < String [], Student > f = Student :: new ;List < Student > stus = readStudent1 ( path , f );stus . forEach ( System . out :: println );}public static List < Student > readStudent1 ( String path ,Function < String [], Student > function ){List < Student > students = new ArrayList <> ();try ( FileReader reader = new FileReader ( path );BufferedReader br = new BufferedReader ( reader )) {String line ;while (( line = br . readLine ()) != null ){String [] arr = line . split ( "," );Student stu = function . apply ( arr );students . add ( stu );}} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();}return students ;}public static List < Student > readStudent ( String path , Function < String , Student > function ){List < Student > students = new ArrayList <> ();try ( FileReader reader = new FileReader ( path );BufferedReader br = new BufferedReader ( reader )) { String line ;while (( line = br . readLine ()) != null ){Student stu = function . apply ( line );students . add ( stu );}} catch ( FileNotFoundException e ) {e . printStackTrace ();} catch ( IOException e ) {e . printStackTrace ();}return students ;}private static class Student {private String name ;private String sex ;private int age ;public Student ( String [] arr ) {this . name = arr [ 0 ];this . sex = arr [ 1 ];this . age = Integer . parseInt ( arr [ 2 ]);}public String getName () {return name ;}public void setName ( String name ) {this . name = name ;}public String getSex () {return sex ;}public void setSex ( String sex ) {this . sex = sex ;}public int getAge () {return age ;}public void setAge ( int age ) {this . age = age ;}@Overridepublic String toString () {return "Student{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", age=" + age +'}' ;}}}