函数式接口
Java8 引入的一个核心概念是函数式接口(Function Interfaces). 通过在接口里面添加一个抽象方法,这些方法可以直接从接口中运行.如果一个接口定义一个唯一的抽象方法,那么这个接口就称为函数式接口.同时,引入了一个新的注解: @FunctionInterface. 可以把它放在一个接口前,表示这个接口是一个函数式接口.这个注解是非必须的,只要接口只包含一个方法,虚拟机会自动判断,不过最好添加注解进行声明,声明之后只允许有一个抽象方法,否则编译器会报错.
java.lang.Runnable 就是一个函数式接口.
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
声明一个接口:
@FunctionalInterface
public interface func{
}
编译报错,no target method ,增加一个方法:
@FunctionalInterface
public interface func{
void dosome();
}
这就是一个函数式接口,如果再加一个方法??
@FunctionalInterface
public interface func{
void dosome();
void doanother();
}
会报错,因为声明函数式接口只能有一个抽象方法.
@FunctionalInterface
public interface func{
@Override
boolean equals(Object o);
void dosome();
}
这种包含两个方法的也是可以的.因为equals方法是Object的public方法,但是只能增加Object的public方法,其他方法是不行的.例如:
@FunctionalInterface
public interface func{
@Override
Object clone();
void dosome();
}
会报错,因为需要Object的public方法,但是clone方法是protected的.
函数式接口,有且只能有一个抽象方法,Object的public方法除外.
package com.lxq;
/**
* Hello world!
*
*/
public class App
{
public static void main(String args[]){
App tester = new App();
// 带有类型声明的表达式
MathOperation addition = (int a, int b) -> a + b;
// 没有类型声明的表达式
MathOperation subtraction = (a, b) -> {return a - b;};
// 带有大括号、带有返回语句的表达式
MathOperation multiplication = (int a, int b) -> { return a * b; };
// 没有大括号和return语句的表达式
MathOperation division = (int a, int b) -> a / b;
// 输出结果
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 没有括号的表达式
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 有括号的表达式
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
// 调用sayMessage方法输出结果
greetService1.sayMessage("Shiyanlou");
greetService2.sayMessage("Classmate");
}
// 下面是定义的一些接口和方法
@FunctionalInterface
interface MathOperation {
int operation(int a, int b);
}
@FunctionalInterface
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}
输出结果:
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Shiyanlou
Hello Classmate
四大内置核心接口
- Predicate 函数式接口
- Function 函数式接口
- Consumer 函数式接口
- Supplier 函数式接口
(1)Predicate 函数式接口
1.Predicate的基本使用
public class Main{
@Test
public void test(){
List<String> list = Arrays.asList("hEOs","AJssS","dsddss","ww");
List<String> strlist = filterStr(list,(s)->s.length()>3);
}
// 需求:将满足条件的字符串放到集合中
public List<String> filterStr(List<String> list, Predicate<String> pre){
List<String> strlist = new ArrayList<>();
for(String str:list){
if(pre.test(str)){
strlist.add(str);
}
}
return strlist;
}
}
2. Predicate的默认方法and、or、negate(取反)
public class Main{
public static void main(String[] args){
Predicate<Integer> p1 = age -> age>18;
Predicate<Integer> p2 = age -> age<30;
//其实就是表达式(age -> age>18)&&(age -> age<30)赋值给and
Predicate<Integer> and = p1.and(p2);
boolean test1 = and.test(20); //返回p1和p2的与结果
out.println(test1); //输出true
}
}
(2)Function 函数式接口
1.Function基本使用
public class Main{
@Test
public void test(){
String newStr = steHandler("这个是 测试 的..",(str)-> str.trim());
System.out.print(newStr);
String newStr1 = steHandler("这个是测试的",(str)-> str.substring(0,3));
System.out.print(newStr1);
}
// 需求:用于处理字符串
public String steHandler(String str, Function<String,String> fun){
return fun.apply(str);
}
}
2.Function的默认方法andThen(协作)
public class Main{
public static void main(String[] args){
//f1参数为String,结果为Boolean
Function<String,Boolean> f1 = s1 -> s1!=null;
Function<Boolean,Integer> f2 = b -> b?1:0;
//将f1的布尔值结果作为f2函数式接口的参数来传递
//所以stringIntegerFunction接收值为f1的参数类型String,返回值类型为f2的返回类型Integer
Function<String,Integer> stringIntegerFunction = f1.andThen(f2);
Integer apply = stringIntegerFunction.apply("111");
out.println(apply); //输出1
}
}
(3)Consumer 函数式接口
1.Consumer的基本使用
public class ConsumerTest {
public static void main(String[] args) {
Consumer<Integer> consumer = (x) -> {
int num = x * 5;
System.out.println(num);
};
Consumer<Integer> consumer1 = (x) -> {
int num = x * 6;
System.out.println(num);
};
consumer.andThen(consumer1).accept(10);
}
}
(4) Supplier函数式接口
1.supplier的基本使用
public class Main{
@Test
public void test(){
List<Integer> list = getNumList(10,()->(int)Math.random()*100);
}
// 需求:产生指定个数的整数,并放入集合中
public List<Integer> getNumList(int num, Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for(int i=0;i<num;i++){
Integer e = sup.get();
list.add(e);
}
return list;
}
}