自学Java——day_22 函数式接口、函数式编程

1.函数式接口的基本常识

函数式接口在Java中是指:有且仅有一个抽象方法的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。

1.1 定义格式

由于接口当中抽象方法的 public abstract 是可以省略的,所以定义一个函数式接口很简单。

public interface MyFunctionalInterface {     
	void myMethod();      
}

1.2 @FunctionalInterface注解

@FunctionalInterface 
public interface MyFunctionalInterface { 
	void myMethod();      
}

1.3 自定义函数式接口

public class Demo09FunctionalInterface {     
	// 使用自定义的函数式接口作为方法参数      
	private static void doSomething(MyFunctionalInterface inter) {      
		inter.myMethod(); // 调用自定义的函数式接口方法          
	}           
	public static void main(String[] args) {      
		// 调用使用函数式接口的方法          
		doSomething(()> System.out.println("Lambda执行啦!"));          
	}      
}

2.函数式编程

有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费。而Lambda表达式是延迟执行的,这正好可以作为解决方案,提升性能。

2.1 性能优化

@FunctionalInterface 
public interface MessageBuilder {       
	String buildMessage();   
}
public class Demo02LoggerLambda {     
	private static void log(int level, MessageBuilder builder) {         
		if (level == 1) {            
			System.out.println(builder.buildMessage());            
		}     
	}
	public static void main(String[] args) {         
		String msgA = "Hello";         
		String msgB = "World";         
		String msgC = "Java";           
		log(1, ()> msgA + msgB + msgC );     
	} 
}
	这样一来,只有当级别满足要求的时候,才会进行三个字符串的拼接;
	否则三个字符串将不会进行拼接。

2.2 使用Lambda作为参数

public class Demo04Runnable {     
	private static void startThread(Runnable task) {        
		new Thread(task).start();        
	}       
	public static void main(String[] args) {        
		startThread(()> System.out.println("线程任务执行!"));        
	} 
}

2.3 使用Lambda作为返回值

import java.util.Arrays; 
import java.util.Comparator;   
public class Demo06Comparator {     
	private static Comparator<String> newComparator() {        
		return (a, b)> b.length() ‐ a.length();        
	}       
	public static void main(String[] args) {         
		String[] array = { "abc", "ab", "abcd" };         
		System.out.println(Arrays.toString(array));         
		Arrays.sort(array, newComparator());         
		System.out.println(Arrays.toString(array));     
	} 
}

3.常见函数式接口

JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供。 下面是简单的几个接口及使用示例。

3.1 Supplier接口

java.util.function.Supplier 接口仅包含一个无参的方法:

  • T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据
public class Demo02Test {     
	//定一个方法,方法的参数传递Supplier,泛型使用Integer     
	public static int getMax(Supplier<Integer> sup){         
		return sup.get();     
	}       
	public static void main(String[] args) {         
		int arr[] = {2,3,4,52,333,23};           
		//调用getMax方法,参数传递Lambda         
		int maxNum = getMax(()>{            
			//计算数组的大值            
			int max = arr[0];            
			for(int i : arr){                
				if(i>max){                    
					max = i;                
				}            
			}            
			return max;         
		});         
		System.out.println(maxNum);     
	} 
}

3.2 Consumer接口

java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。

3.2.1 抽象方法【accept】

Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。

import java.util.function.Consumer;   
public class Demo09Consumer {     
	private static void consumeString(Consumer<String> function) {        
		function.accept("Hello");        
	}       
	public static void main(String[] args) {         
		consumeString(s ‐> System.out.println(s));     
	} 
}

3.2.2 默认方法【andThen】

如果一个方法的参数和返回值全都是 Consumer 类型,那么就可以实现效果:消费数据的时候,首先做一个操作,然后再做一个操作,实现组合。而这个方法就是 Consumer 接口中的default方法 andThen 。

import java.util.function.Consumer;   
public class Demo10ConsumerAndThen {     
	private static void consumeString(Consumer<String> one, Consumer<String> two) {        
		one.andThen(two).accept("Hello");        
	}       
	public static void main(String[] args) {         
		consumeString(
			s ‐> System.out.println(s.toUpperCase()),             
			s ‐> System.out.println(s.toLowerCase())
		);
	} 
}

3.3 Predicate接口

有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用 java.util.function.Predicate 接口。

3.3.1 抽象方法【test】

Predicate 接口中包含一个抽象方法: boolean test(T t) 。

import java.util.function.Predicate;   
public class Demo15PredicateTest {     
	private static void method(Predicate<String> predicate) {         
		boolean veryLong = predicate.test("HelloWorld");         	
		System.out.println("字符串很长吗:" + veryLong);     
	}       
	public static void main(String[] args) {         
		method(s ‐> s.length() > 5);     
	} 
}

3.3.2 默认方法【and】

既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起来实现“并且”的效果时,可以使用default方法 and 。

import java.util.function.Predicate;   
public class Demo16PredicateAnd {     
	private static void method(Predicate<String> one, Predicate<String> two) {         
		boolean isValid = one.and(two).test("Helloworld");         
		System.out.println("字符串符合要求吗:" + isValid);     
	}       
	public static void main(String[] args) {         
		method(s ‐> s.contains("H"), s ‐> s.contains("W"));     
	} 
}

3.3.3 默认方法【or】

与 and 的“与”类似,默认方法 or 实现逻辑关系中的“或”。

import java.util.function.Predicate;   
public class Demo16PredicateAnd {     
	private static void method(Predicate<String> one, Predicate<String> two) {         
		boolean isValid = one.or(two).test("Helloworld");         
		System.out.println("字符串符合要求吗:" + isValid);     
	}       
	public static void main(String[] args) {         
		method(s ‐> s.contains("H"), s ‐> s.contains("W"));     
	} 
}

3.3.4 默认方法【negate】

“与”、“或”已经了解了,剩下的“非”(取反)也会简单。

import java.util.function.Predicate;   
public class Demo17PredicateNegate {     
	private static void method(Predicate<String> predicate) {         
		boolean veryLong = predicate.negate().test("HelloWorld");         
		System.out.println("字符串很长吗:" + veryLong);     
	}       
	public static void main(String[] args) {        
		method(s ‐> s.length() < 5);        
	} 
}

3.4 Function接口

java.util.function.Function 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。

3.4.1 抽象方法【apply】

Function 接口中主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。

使用的场景例如:将 String 类型转换为 Integer 类型。

import java.util.function.Function;   
public class Demo11FunctionApply {     
	private static void method(Function<String, Integer> function) {         
		int num = function.apply("10");         
		System.out.println(num + 20);     
	}       
	public static void main(String[] args) {         
		method(s ‐> Integer.parseInt(s));     
	} 
}

3.4.2 默认方法【andThen】

Function 接口中也有一个默认的 andThen 方法,用来进行组合操作。

import java.util.function.Function;   
public class Demo12FunctionAndThen {     
	private static void method(Function<String, Integer> one, Function<Integer, Integer> two) {         
		int num = one.andThen(two).apply("10");         
		System.out.println(num + 20);     
	}       
	public static void main(String[] args) {         
		method(str‐>Integer.parseInt(str)+10, i ‐> i *= 10);     
	} 
}

你可能感兴趣的:(java基础知识)