2 函数式接口
2.1 主要信息:
Note that instances of functional interfaces can be created with lambda expressions, method references, or constructor references.
(重点)an interface declares an abstract method overriding one of the public methods of {@codejava.lang.Object}, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implementation from {@code java.lang.Object} or elsewhere.
The type is an interface type and not an annotation type, enum, or class. The annotated type satisfies the requirements of a functional interface.
the compiler will treat any interface meeting the definition of a functional interface as a functional interface regardless of whether or not a {@code FunctionalInterface} annotation is present on the interface declaration.
2.2 关于函数式接口的条件:
- 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口。
- 如果我们在某个接口上声明了 FunctionInterface 注解,则编译器会按照函数式接口的定义来要求该接口
- 如果某个接口只有一个抽象方法,但我们没有给该接口声明 FunctionInterface 注解,那么编译器依旧会将该接口看作是函数是借口
注意: 重写Object对象方法不计算在接口个数上
2.3 函数式接口的实现方法
-
lambda 实现
-
方法应用: 四种情况,这里简单介绍
- 类::非静态方法: 非静态方法没有参数,且一般必须是由实例来调用,所以用这个实现接口,必会有个对应的实例调用这各方法。Function<String,String> 第一个参数就是输入参数,刚好是是String类型,可以调用toUpperCase方法
- 类::静态方法:静态方法需要参数类型与函数相同
- 类::new:构造器引用实现,要求参数符合
// 函数 String toUpperCasre(); 类::非静态方法,
Function<String, String> function = String::toUpperCase;
// 断言 Object.isNull(Object); 类::静态方法
Predicate<Object> predicate = Objects::isNull;
// 供应商 new Student(); 类::new 对象
Supplier<Student> supplier1 = Student::new;
- 构造函数实现
java8后接口出现了接口默认方法、方法 default 、静态方法、内部迭代、外部迭代
2.4 java.util.function 下常用函数式接口
2.4.1 Consumer 消费行为
接受单个参数,不返还任何结果 接收 T, 用 accept(T t) 消费 执行这个动作
常在迭代中出现: list.forEach(Consumer) 这个是集合新出的遍历方法、Stram.forEach(Consumer) 这是流的元数据的遍历方法
package cn.zxhysy.jdk8;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class Test1 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
//
// for(int i = 0; i < list.size(); ++i) {
// System.out.print(" " + list.get(i));
// }
// System.out.println("\n---------------");
// for(Integer i: list) {
// System.out.print(" " + i);
// }
// System.out.println("\n---------------");
// list.forEach(new Consumer<Integer>() {
// @Override
// public void accept(Integer integer) {
// System.out.print(" " + 2 * integer);
// }
// });
// list.forEach(i -> System.out.println(i));
/* 通过方法引用的形式来创建Lambda表达式 */
list.forEach(System.out::println);
}
}
2.4.2 Function<T,R> 单参数函数
接收两个类型,第一个是输入参数,第二个是输出(表示返回参数)通过使用 R apply(T t) 达到目的
package cn.zxhysy.jdk8;
import javax.sound.midi.Soundbank;
import java.util.function.Function;
public class FunctionTest {
public static void main(String[] args) {
FunctionTest test = new FunctionTest();
int compute = test.compute(1, value -> 2 * value);
System.out.println(compute);
System.out.println(test.compute(3, value -> value * value));
System.out.println(test.convert(4, value -> String.valueOf(value+"hello word")));
System.out.println(test.method1(2));
}
public int compute(int a, Function<Integer, Integer> function){
return function.apply(a);
}
public String convert(int a, Function<Integer, String> function){
return function.apply(a);
}
public int method1(int a){
return 2+a;
}
public int method2(int a){
return 2+a;
}
public int method3(int a){
return 2+a;
}
}
Function 默认接口实现:
default Function<V, R> compose<Function<> before) 先应用before 再应用当前对象Fun, 简单就是说就是执行before.apply之后的值传递给自己对象进行this.apply
andTen(Function after) 先应用当前对象Fun 再应用 after
static Function<T,T> identity() 返回输入元素
public class FunctionTest2 {
public static void main(String[] args) {
FunctionTest2 test = new FunctionTest2();
System.out.println(test.compute(2, value -> value * 3, value -> value * value)); // 2²*3 = 12
System.out.println(test.compute2(2, value -> value * 3, value -> value * value)); // (2*3)² = 36
}
public int compute(int a, Function<Integer,Integer> function1, Function<Integer,Integer> function2){
return function1.compose(function2).apply(a);
}
public int compute2(int a, Function<Integer,Integer> function1, Function<Integer,Integer> function2){
return function1.andThen(function2).apply(a);
}
}
2.4.3 BiFunction<T, U, R> 双参数函数
R apply(T t, U u) 接收2个参数,返回操作结果集
// 1 和 2 四则运算
System.out.println(test.compute3(1, 2,(value1, value2) -> value1 + value2));
System.out.println(test.compute3(1, 2,(value1, value2) -> value1 - value2));
System.out.println(test.compute3(1, 2,(value1, value2) -> value1 * value2));
System.out.println(test.compute3(1, 2,(value1, value2) -> value1 / value2));
System.out.println(test.compute4(1, 2,(value1, value2) -> value1 + value2, value -> value*value));
public int compute3(int a, int b, BiFunction<Integer, Integer, Integer> biFunction){
return biFunction.apply(a,b);
}
public int compute4(int a, int b, BiFunction<Integer, Integer, Integer> biFunction, Function<Integer,Integer> function){
return biFunction.andThen(function).apply(a, b);
}
map(Function) 映射值,值在操作后返回流
list.stream().map(item -> item.toUpperCase()).forEach(item -> System.out.println(item));
上面代码就是 list 转 流,通过 map 方法操作流的元,遍历每个集合中的数据,变成大写,再用 forEach 遍历,可换写为方法引用实现函数式接口
list.stream().map(String::toUpperCase).forEach(System.out::println);
2.4.4 Predicate< T > 断言
返回一个boolean值,由 boolean test(T t) 方法实现操作
Predicate 实现的方法:
-
default Predicate and(Predicate<? super T> other) 并且
-
default Predicate negate() 取反
-
default Predicate or(Predicate<? super T> other) 或者
-
static Predicate isEqual(Object targetRef) 判断两个参数是否相等返回一个函数
static <T> Predicate<T> isEqual(Object targetRef){ return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }
package cn.zxhysy.jdk8;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
public class PredicateTest2 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
PredicateTest2 predicateTest2 = new PredicateTest2();
// 偶数
predicateTest2.conditionFilter(list, item -> item % 2 == 0);
System.out.println("------------------");
// 奇数
predicateTest2.conditionFilter(list, item -> item % 2 != 0);
System.out.println("------------------");
// > 3
predicateTest2.conditionFilter(list, item -> item > 3);
System.out.println("------------------");
// < 5
predicateTest2.conditionFilter(list, item -> item < 5);
System.out.println("------------------");
// 打印全部
predicateTest2.conditionFilter(list, item -> true);
System.out.println("------------------");
// >5 偶数 方法带上取反
predicateTest2.conditionFilter2(list, item -> item > 5, item -> item % 2 ==0);
// Predicate<Integer> predicate = Objects::isNull;
// boolean test = predicate.test(13);
// System.out.println(test);
System.out.println(predicateTest2.isEqual("test").test("test"));
}
public void conditionFilter(List<Integer> list, Predicate<Integer> predicate){
for (Integer integer: list) {
if (predicate.test(integer)){
System.out.println(integer);
}
}
}
public void conditionFilter2(List<Integer> list, Predicate<Integer> predicate1, Predicate<Integer> predicate2){
for (Integer integer: list) {
// negate 取反
if (predicate1.and(predicate2).negate().test(integer)){
System.out.println(integer);
}
}
}
public Predicate<String> isEqual(Object object){
return Predicate.isEqual(object);
}
}
fliter(Predicate<>) 过滤
collect(Collectors.toList()); 将流转换为list集合
package cn.zxhysy.jdk8;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
public class PersonTest {
public static void main(String[] args) {
Person person1 = new Person("zhangsan", 13);
Person person2 = new Person("lisi", 25);
Person person3 = new Person("wangwu", 30);
List<Person> persons = Arrays.asList(person1,person2,person3);
PersonTest test = new PersonTest();
// List<Person> personResult = test.gePersonByUserName("zhangsan", persons);
// personResult.forEach(person -> System.out.println(person.getUsername()));
// List<Person> personResult = test.getPersonByAge(20, persons);
// personResult.forEach(person -> System.out.println(person.getUsername()));
List<Person> personResult = test.getPersonByAge2(20, persons, (age, personList) -> personList.stream().filter(person -> person.getAge() > age).collect(Collectors.toList()));
personResult.forEach(person -> System.out.println(person.getUsername()));
System.out.println("--------------------------");
List<Person> personResult2 = test.getPersonByAge2(20, persons, (age, personList) -> personList.stream().filter(person -> person.getAge() < age).collect(Collectors.toList()));
personResult2.forEach(person -> System.out.println(person.getUsername()));
}
public List<Person> gePersonByUserName(String username, List<Person> persons){
return persons.stream().filter(person -> person.getUsername().equals(username)).collect(Collectors.toList());
}
public List<Person> getPersonByAge(Integer age, List<Person> persons) {
BiFunction<Integer, List<Person>, List<Person>> biFunction = (ageOfPerson, personList) -> personList.stream().filter(person -> person.getAge() > ageOfPerson).collect(Collectors.toList());
return biFunction.apply(age, persons);
}
public List<Person> getPersonByAge2(Integer age, List<Person> persons, BiFunction<Integer, List<Person>, List<Person>> biFunction){
return biFunction.apply(age, persons);
}
}
2.4.5 Supplier 供应商
不接收参数同时返回一个结果, 由 T get() 实现
package cn.zxhysy.jdk8;
import java.util.function.Supplier;
public class SupplierTest {
public static void main(String[] args) {
// 可用于工厂模式
Supplier<String> supplier = () -> "hello World";
System.out.println(supplier.get());
}
}
测试下工厂模式:
package cn.zxhysy.jdk8;
public class Student {
private String name = "zhangsan";
private int age = 20;
public Student(){};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package cn.zxhysy.jdk8;
import java.util.function.Supplier;
public class StudentTest {
public static void main(String[] args) {
Supplier<Student> supplier = () -> new Student();
System.out.println(supplier.get().getName());
System.out.println("---------------------------");
// 不接受参数,返回对象
Supplier<Student> supplier1 = Student::new;
System.out.println(supplier1.get().getName());
}
}
2.4.6 BinaryOperatoer extend BiFunction<T, T, T> 二元操作
是一个特殊的二元参数操作。接受一种类型并返回同种类型的 BiFunction 函数。用 T apply(T t, T r) 实现
BinaryOperatoer 静态方法
static BinaryOperator minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
通过比较器比较返回的值判断返回较小值
static BinaryOperator maxBy(Comparator<? super T> comparator) 通过比较器比较返回的值判断返回较小值
package cn.zxhysy.jdk8;
import java.util.Comparator;
import java.util.function.BinaryOperator;
public class BinaryOperatorTest {
public static void main(String[] args) {
BinaryOperator<Integer> binaryOperator = (value1,value2) -> value1 + value2;
System.out.println(binaryOperator.apply(13,16));
System.out.println("-------------------");
BinaryOperatorTest test = new BinaryOperatorTest();
System.out.println(test.operator(15, 26, (val1, val2) -> val1 * val2));
System.out.println("-------------------");
// BinaryOperator<Integer> integerBinaryOperator = BinaryOperator.minBy(new Comparator<Integer>() {
// @Override
// public int compare(Integer o1, Integer o2) {
// return Integer.compare(o1, o2);
// }
// });
// BinaryOperator<Integer> integerBinaryOperator = BinaryOperator.minBy((o1, o2) -> o1 - o2);
// 上面注释的两种写法都可以被改进为下面的方法
// minBy 静态方法接收的是 Comparator 返回 BinaryOperator实例
// BinaryOperator实例 通过调用 apply 方法接受参数(两个值)传递到 minBy(此时minBy就是apply的实现方法), minBy 再调用比较器 Comparator
// 而比较器Comparator实例是由 comparingInt 静态方法通过接受 ToIntFunction 函数applyAsInt方法获取两个对象的值再相减作为方法体生成的实例
BinaryOperator<Integer> integerBinaryOperator3 = BinaryOperator.minBy(Comparator.comparingInt(o -> o));
System.out.println(test.operator(13, 12, integerBinaryOperator3));
// 上面方法改进采用这种方式
System.out.println(test.operatorComparator(13, 12, Comparator.comparingInt(o -> o)));
System.out.println("-------------------");
// 同样道理
System.out.println(test.strOperatorMinBy("dfsa","wangas", Comparator.comparingInt(String::length)));
}
public int operator(int val1, int val2, BinaryOperator<Integer> binaryOperator){
return binaryOperator.apply(val1, val2);
}
public int operatorComparator(int val1, int val2, Comparator<Integer> comparator){
return BinaryOperator.maxBy(comparator).apply(val1, val2);
}
public String strOperatorMinBy(String val1, String val2, Comparator<String> comparator){
return BinaryOperator.maxBy(comparator).apply(val1, val2);
}
}