jdk8中几个核心的函数式接口笔记
1. Function接口
/**
* function 接口测试
* function 函数只能接受一个参数,要接受两个参数,得使用BiFunction接口
*/
public class FunctionTest {
@Test
public void Test (){
FunctionTest test = new FunctionTest();
// System.out.println(test.compute(4, x->x*2));
System.out.println(test.compute(2, v -> v * 3, v -> v * v));
System.out.println(test.compute2(2, v -> v * 3, v -> v * v));
System.out.println(test.compute3(2,3, (a, b)-> a+b));
System.out.println(test.compute4(2, 3, (a, b) -> a + b, a -> a * a));
}
/**
* function的第一个参数是输入, 第二个参数是输出
* @param a
* @param function
* @return
*/
public int compute(int a, Function<Integer, Integer> function) {
int result = function.apply(a);
return result;
}
/**
* compose 组合, 先执行传入的参数方法,再执行本身的方法
* @param a 输入
* @param func1 本身方法
* @param func2 传入的参数方法
* @return
*/
public int compute(int a, Function<Integer, Integer> func1, Function<Integer, Integer> func2) {
return func1.compose(func2).apply(a);
}
/**
* andThen 方法,先执行自己的方法,再执行传入的参数方法
* @param a
* @param func1 本身方法
* @param func2 传入的参数方法
* @return
*/
public int compute2(int a, Function<Integer, Integer> func1, Function<Integer, Integer> func2) {
return func1.andThen(func2).apply(a);
}
/**
* biFunction接口可传入两个参数
* @param a
* @param b
* @param biFunction
* @return
*/
public int compute3(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {
return biFunction.apply(a, b);
}
/**
* biFunction只有一个andThen方法(参数还是Function),因为他只返回一个值,不能返回两个值
* @param a
* @param b
* @param biFunction
* @param function
* @return
*/
public int compute4(int a, int b, BiFunction<Integer, Integer, Integer> biFunction, Function<Integer, Integer> function) {
return biFunction.andThen(function).apply(a,b);
}
}
// 模仿Function接口, 接受一个参数, 返回一个值
@FunctionalInterface
interface FakeInterface<J, R> {
R fuck(J t);
}
public class MyTest {
public String myTest(Integer a, FakeInterface<Integer, String> fakeInterface) {
System.out.println("执行我的fakeInterface中的方法, 传入一个参数");
String s = fakeInterface.fuck(a);
return s;
}
public static void main(String[] args) {
MyTest myTest = new MyTest();
String s = myTest.myTest(5, x -> String.valueOf(x));
System.out.println(s);
}
}
2. BiFunction接口
public class PersonTest {
@Test
public void test1() {
Person p1 = new Person("zhangsan", 20);
Person p2 = new Person("lisi", 30);
Person p3 = new Person("wangwu", 40);
List<Person> persons = Arrays.asList(p1, p2, p3);
PersonTest test = new PersonTest();
List<Person> result = test.getPersonByAge(30, persons);
result.forEach(x-> System.out.println(x.getUsername()));
}
@Test
public void test2() {
Person p1 = new Person("zhangsan", 20);
Person p2 = new Person("lisi", 30);
Person p3 = new Person("wangwu", 40);
List<Person> persons = Arrays.asList(p1, p2, p3);
PersonTest test = new PersonTest();
List<Person> result = test.getPersonByAge2(30, persons, (age, personList) -> {
return personList.stream().filter(p->p.getAge() > age).collect(Collectors.toList());
});
result.forEach(x-> System.out.println(x.getUsername()));
}
/**
* 强行使用lamboda来写代码
* @param age
* @param persons
* @return
*/
public List<Person> getPersonByAge(int 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);
}
/**
* 不预先定义函数操作
* @param age
* @param persons
* @param biFunction 函数操作由用户传入,更加灵活
* @return
*/
public List<Person> getPersonByAge2(int age, List<Person> persons, BiFunction<Integer, List<Person>, List<Person>> biFunction) {
// 执行函数操作
return biFunction.apply(age, persons);
}
3. Predicate接口
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* predicate接口, 是一个根据给定参数来决定返回bool值的判断式函数式接口
*/
public class PredicateTest {
@Test
public void Test1() {
Predicate<String> predicate = p->p.length() > 5;
System.out.println(predicate.test("hello"));
}
// 接口的简单练习
@Test
public void Test2() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
PredicateTest predicateTest = new PredicateTest();
System.out.println("打印出偶数: ");
predicateTest.conditionFilter(list, item->(item & 1) == 0);
System.out.println("---------------------------");
System.out.println("打印出奇数: ");
predicateTest.conditionFilter(list, item->(item & 1) == 1);
System.out.println("---------------------------");
predicateTest.conditionFilter(list, x->true);
System.out.println("----------------------------");
System.out.println("打印:, 大于5,并且偶数: ");
predicateTest.conditionAndFilter(list, x -> x > 5, x -> (x & 1) == 0);
System.out.println("----------------------------");
}
/**
* 函数式编程的一大特点就是将行为提到方法外面,由用户传入
* 调用时动态传入动作,更高层次的抽象化
* @param list
* @param predicate
*/
public void conditionFilter(List<Integer> list, Predicate<Integer> predicate) {
// 将通过条件判断的数字打印出来
for (Integer i : list) {
if (predicate.test(i)) {
System.out.println(i);
}
}
}
/**
* predicate接口的 与 运算, 打印出符合两个条件的结果
同理, 可理解predict中的其他逻辑运算
* @param list
* @param p1
* @param p2
*/
public void conditionAndFilter(List<Integer> list, Predicate<Integer> p1, Predicate<Integer> p2) {
for (Integer i : list) {
if (p1.and(p2).test(i)) {
System.out.println(i);
}
}
}
/**
* Predicate.isEqual() 方法用于判断两个参数是否相同, 依据就是 Objects#equals(Object, Object)}.
* 这个方法不怎么好理解, 说白了,就是调用传入参数的equals方法,
* 得到其方法的引用,而这个引用又刚好符合Predict函数的格式,可以作为Predict来使用
* @param object
* @return
*/
public Predicate<String> isEqual(Object object) {
return Predicate.isEqual(object);
}
@Test
public void Test3() {
PredicateTest predicateTest = new PredicateTest();
System.out.println(predicateTest.isEqual("test").test("test")); // true
System.out.println(predicateTest.isEqual("test").test("test2")); // false
System.out.println(predicateTest.isEqual(null).test("test")); // false
System.out.println(predicateTest.isEqual(null).test(null)); //true
}
}
4. Supplier接口
@Data
public class Student {
private String name = "zhangsan";
private Integer age = 20;
}
/**
* Supplier接口, 不接受参数, 返回一个结果
* 常用于 工厂
*
*/
public class SupplierTest {
// 最简单例子
@Test
public void Test() {
Supplier<String> supplier = () -> "hello world";
System.out.println(supplier.get());
}
/**
* 利用supplier生产学生
*/
@Test
public void Test2() {
Supplier<Student> supplier = ()->new Student();
System.out.println(supplier.get().toString());
// 更进一步, 调用Student的构造方法, 叫做构造方法的引用
// 不接受参数, 返回Student对象,符合函数式接口的要求
// 编译器会去Student找不带参数, 返回Student的构造方法
Supplier<Student> supplier2 = Student::new;
System.out.println(supplier2.get().toString());
}
}
5. Consumer接口
接收一个参数, 不返回值, 但可能改变传入的参数,通过这个改变的副作用来实现业务,list.forEach中就是一个Consumer接口作为参数
list.forEach(x->System.out.println(x));
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
public class MyTest {
public void myTest2(Integer a, Consumer<Integer> consumer) {
consumer.accept(a);
}
public static void main(String[] args) {
MyTest myTest = new MyTest();
myTest.myTest2(5, x-> {
System.out.println("可以操作x,但没有返回值");
});
}
}
jdk8中几个核心的函数式接口笔记的更多相关文章
- 乐字节-Java8核心特性实战之函数式接口
什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一 ...
- Java8内置的四大核心函数式接口
package java_8; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import j ...
- Java8新特性(一)——Lambda表达式与函数式接口
一.Java8新特性概述 1.Lambda 表达式 2. 函数式接口 3. 方法引用与构造器引用 4. Stream API 5. 接口中的默认方法与静态方法 6. 新时间日期 API 7. 其他新特 ...
- Java 8 特性 —— 函数式接口
函数式接口 概述:接口中只有一个抽象方法. 函数式接口,即适用于函数式编程场景的接口.而 Java 中的函数式编程体现就是 Lambda,所以函数式接口就是可以适用于 Lambda 使用的接口.只有确 ...
- JAVA8之函数式接口
由于JDK8已经发布一段时间了,也开始逐渐稳定,未来使用JAVA语言开发的系统会逐渐升级到JDK8,因为为了以后工作需要,我们有必要了解JAVA8的一些新的特性.JAVA8相对JAVA7最重要的一个突 ...
- Java8 新特性 函数式接口
什么是函数式接口 函数式接口是Java8引用的一个新特性,是一种特殊的接口:SAM类型的接口(Single Abstract Method).但是它还是一个接口,只是有些特殊罢了. 函数式接口的 ...
- java8学习之Supplier与函数式接口总结
Supplier接口: 继续学习一个新的函数式接口--Supplier,它的中文意思为供应商.提供者,下面看一下它的javadoc: 而具体的方法也是相当的简单,就是不接受任何参数,返回一个结果: 对 ...
- JDK8中Stream使用解析
JDK8中Stream使用解析 现在谈及JDK8的新特新,已经说不上新了.本篇介绍的就是Stream和Lambda,说的Stream可不是JDK中的IO流,这里的Stream指的是处理集合的抽象概念『 ...
- Java8 函数式接口 @FunctionalInterface以及常用Consumer<T>、Supplier<T>、Function<T, R>、Predicate<T>总结
首先看看什么是Lambda 表达式 Lambda是一个匿名函数,我们可以把Lambda表达式理解为一段可以传递的代码(将代码像数据一样传递):最简单的Lambda表达式可由逗号分隔的参数列表.-> ...
随机推荐
- explicit作用
在C++中,explicit关键字用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换. explicit使用注意事项: explicit 关键字只能用 ...
- hdu 1695 欧拉函数+容斥原理
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- ELK+Filebeat+redis整合
前面的博客,有具体的ELK安装配置步骤,此处在其基础上修改 修改配置文件并启动 [root@topcheer filebeat-6.2.3-linux-x86_64]# vim filebeat.ym ...
- (46)LINUX应用编程和网络编程之一Linux应用编程框架
3.1.1.应用编程框架介绍 3.1.1.1.什么是应用编程 (1)整个嵌入式linux核心课程包括5个点,按照学习顺序依次是:裸机.C高级.uboot和系统移植.linux应用编程和网络编程.驱动. ...
- Mongodb分片副本集集群搭建
一.环境准备 1.1.主机信息(机器配置要求见硬件及开发标准规范文档V1.0) 序号 主机名 IP 1 DB_01 10.202.105.52 2 DB_02 10.202.105.53 3 DB_0 ...
- Python爬取中文页面的时候出现的乱码问题
一.读取返回的页面数据 在浏览器打开的时候查看源代码,如果在头部信息中指定了UTF-8 那么再python代码中读取页面信息的时候,就需要指定读取的编码方式: response.read().deco ...
- Starting MySQL... ERROR! The server quit without updating PID file (/usr/local/mysql/data/VM_0_6_centos.pid)
刚接触MySql数据库,参考一些文章后搭建起来了也创建了数据库,程序跑到很好,一觉醒来突然连接不上了 MySql数据库了. 研究了好一会才找到原因. 现象: 登录数据库失败 [root@VM_0_6_ ...
- iOS SDK开发之 .framework静态库
查看.a静态库的生成及使用单击此处 注:这篇教程将只使用一小部分Objective-C代码,本文主要讲解从开始到应用的详细步骤.环境:xcode 9.2下面我们开始操作: 第一步:创建一个静态库工程 ...
- 前端必须掌握的 docker 技能(3)
概述 作为一个前端,我觉得必须要学会使用 docker 干下面几件事: 部署前端应用 部署 nginx 给部署的 nginx 加上 https 使用 docker compose 进行部署 给 ngi ...
- maven项目的导包问题,已经加载jar包了可是idea检测不到
1.详细请参考 https://blog.csdn.net/brainhang/article/details/76725080 把测试模式注释即可