java8 lambda this,2020了你还不会Java8新特性?Lambda表达式及API(二)

lambda表达式

为什么要使用lambda表示式

在Java中无法将函数座位参数传递给一个方法,也无法返回一个函数的方法。

在js中,函数的参数是一个函数。返回值是另一个函数的情况是非常常见的。是一门经典的函数式语言。

Java匿名内部类。

匿名内部类的介绍

Gradle的使用。可以完全使用maven的中央仓库。

进行安卓的开发时,gradle已经成为标配了。

lambda:

匿名内部类

my_jButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

System.out.println("Button Pressed! ");

}

});

改造后

my_jButton.addActionListener(e -> System.out.println("Button Pressed!"));

lambda表达式的基本结构:

(param1,param2,param3) ->{

}

函数式编程: 一个接口里边只有一个抽象方法。

可以通过lambda表达式来实例。

关于函数式接口:

如果一个借口只有一个抽象方法,那么该接口就是一个函数式接口。

如果我们在某一个接口上声明了functionalInterface注解,那么编译器就会按照函数是借口的定义来要求改接口。

如果某个接口只有一个抽象方法,但是我们并没有给接口声明functionnaleInterface注解,编译器依旧会给改接口看作是函数式接口。

通过实例对函数式接口的理解:

package com.erwa.jdk8;

@FunctionalInterface

interface MyInterface {

void test();

// Multiple non-overriding abstract methods found in interface com.erwa.jdk8.MyInterface

// void te();

//如果一个接口声明一个抽象方法,但是这个方法重写了 object类中的一个方法.

//接口的抽象方法不会加一.所以依然是函数方法.

// Object 类是所有类的父类.

@Override

String toString();

}

public class Test2 {

public void myTest(MyInterface myInterface) {

System.out.println(1);

myInterface.test();

System.out.println(2);

}

public static void main(String[] args) {

Test2 test2 = new Test2();

test2.myTest(() -> {

System.out.println(3);

});

}

}

接口里边从1.8开始也可以有方法实现了。default

默认方法。

default void forEach(Consumer super T> action) {

Objects.requireNonNull(action);

for (T t : this) {

action.accept(t);

}

}

*

Note that instances of functional interfaces can be created with

* lambda expressions, method references, or constructor reference

lambda表达式的作用:

lambda表达式为Java添加了确实的函数式编程特性,使我们能将函数当做一等公民看待。

在将函数座位一等公民的语言中,lambda表达式的类型是函数。但是在Java中,lambda表达式是对象,他们必须依附于一类特别的对象类型-函数式接口(function interface)

迭代的方式:

外部迭代:

内部迭代:

方法引用:

list.forEach(System.out::println);

接口中可以有默认方法和静态方法。

流: stream

/**

* Returns a sequential {@code Stream} with this collection as its source.

*

*

This method should be overridden when the {@link #spliterator()}

* method cannot return a spliterator that is {@code IMMUTABLE},

* {@code CONCURRENT}, or late-binding. (See {@link #spliterator()}

* for details.)

*

* @implSpec

* The default implementation creates a sequential {@code Stream} from the

* collection's {@code Spliterator}.

*

* @return a sequential {@code Stream} over the elements in this collection

* @since 1.8

*/

default Stream stream() {

return StreamSupport.stream(spliterator(), false);

}

关于流方式实现的举例:

public static void main(String[] args) {

//函数式接口的实现方式

MyInterface1 i1 = () -> {};

System.out.println(i1.getClass().getInterfaces()[0]);

MyInterface2 i2 = () -> {};

System.out.println(i2.getClass().getInterfaces()[0]);

// 没有上下文对象,一定会报错的.

// () -> {};

//通过lambda来实现一个线程.

new Thread(() -> System.out.println("hello world")).start();

//有一个list ,将内容中的首字母变大写输出.

List list = Arrays.asList("hello","world","hello world");

//通过lambda来实现所有字母编程大写输出.

// list.forEach(item -> System.out.println(item.toUpperCase()));

//把三个单词放入到新的集合里边.

List list1 = new ArrayList<>(); //diamond语法. 后边的<>不用再放类型

// list.forEach(item -> list1.add(item.toUpperCase()));

// list1.forEach(System.out::println);

//进一步的改进. 流的方式

// list.stream();//单线程

// list.parallelStream(); //多线程

list.stream().map(item -> item.toUpperCase()).forEach(System.out::println);//单线程

list.stream().map(String::toUpperCase).forEach(System.out::println);

//上边的两种方法,都满足函数式接口的方式.

}

lambda表达式的作

传递行为,而不仅仅是值

提升抽象层次

API重用性更好

更加灵活

lambda基本语法

(argument) -> (body)

如: (arg1,arg2...) -> (body)

Java lambda结构

一个Lambda表达式可以有0个或者多个参数

参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a) 与 (a) 效果相同

所有参数包含在圆括号内,参数之间用逗号相隔。

空圆括号代表参数集为空。

当只有一个参数,且类型可推倒时。圆括号()可省略。

lambda表达式的主体可以包含0条或多条语句。

如果lambda表达式的主体只有一条语句,花括号{}可以省略,匿名函数的返回类型与该主体表达式一致。

如果lambda表达式的主体包含一条以上语句,则表达式必须包含在花括号中。匿名函数的韩绘制类型与代码块的返回类型一致,诺没有反回则为空。

高阶函数:

如果一个函数接收一个函数作为参数,或者返回一个函数作为返回值,那么该函数就叫做高阶函数.

传递行为的举例:

public static void main(String[] args) {

// 函数的测试

// 传递行为的一种方式.

FunctionTest functionTest = new FunctionTest();

int compute = functionTest.compute(1, value -> 2 * value);

System.out.println(compute);

System.out.println(functionTest.compute(2,value -> 5+ value));

System.out.println(functionTest.compute(3,a -> a * a));

System.out.println(functionTest.convert(5, a -> a + "hello "));

/**

* 高阶函数:

* 如果一个函数接收一个函数作为参数,或者返回一个函数作为返回值,那么该函数就叫做高阶函数.

*/

}

//使用lambda表达式的话,可以直觉预定义行为.用的时候传递.

// 即 函数式编程.

public int compute(int a, Function function) {

return function.apply(a);

}

public String convert(int a, Function function) {

return function.apply(a);

}

// 之前完成行为的做法. 提前把行为定义好,用的时候调用方法. 如:

public int method1(int a ){

return a * 2 ;

}

Function类中提供的默认方法的讲解:

/**

* Returns a composed function that first applies the {@code before}

* function to its input, and then applies this function to the result.

* If evaluation of either function throws an exception, it is relayed to

* the caller of the composed function.

返回一个组合的函数。对应用完参数后的结果,再次运行apply

*

* @param the type of input to the {@code before} function, and to the

* composed function

* @param before the function to apply before this function is applied

* @return a composed function that first applies the {@code before}

* function and then applies this function

* @throws NullPointerException if before is null

*

* @see #andThen(Function)

*/

default Function compose(Function super V, ? extends T> before) {

Objects.requireNonNull(before);

return (V v) -> apply(before.apply(v));

}

/**

* Returns a composed function that first applies this function to

* its input, and then applies the {@code after} function to the result.

* If evaluation of either function throws an exception, it is relayed to

* the caller of the composed function.

*

* @param the type of output of the {@code after} function, and of the

* composed function

* @param after the function to apply after this function is applied

* @return a composed function that first applies this function and then

* applies the {@code after} function

* @throws NullPointerException if after is null

*

* @see #compose(Function)

*/

default Function andThen(Function super R, ? extends V> after) {

Objects.requireNonNull(after);

return (T t) -> after.apply(apply(t));

}

compose : 组合function, 形成两个function的串联。 先执行参数

andThen :先应用当前的函数apply,然后再当做参数再次执行apply。 后执行参数。

identity:输入什么返回什么。

BiFunction: 整合两个函数的方法。

为什么BiFunction不提供 compose ,只提供andThen呢?

因为如果提供compose方法的话,只能获取一个参数的返回值。不合理。

public static void main(String[] args) {

FunctionTest2 functionTest2 = new FunctionTest2();

// compose

// System.out.println(functionTest2.compute(2,a -> a * 3,b -> b * b));

// andThen

// System.out.println(functionTest2.compute2(2,a -> a * 3,b -> b * b));

//BiFunction

// System.out.println(functionTest2.compute3(1,2, (a,b) -> a - b));

// System.out.println(functionTest2.compute3(1,2, (a,b) -> a * b));

// System.out.println(functionTest2.compute3(1,2, (a,b) -> a + b));

// System.out.println(functionTest2.compute3(1,2, (a,b) -> a / b));

//BiFunction andThen

System.out.println(functionTest2.compute4(2,3,(a,b) ->a + b , a -> a * a ));

}

//compose : 组合function, 形成两个function的串联。 先执行参数

//andThen :先应用当前的函数apply,然后再当做参数再次执行apply。 后执行参数

public int compute(int a, Function function1, Function function2) {

return function1.compose(function2).apply(a);

}

public int compute2(int a, Function function1, Function function2) {

return function1.andThen(function2).apply(a);

}

//BiFunction

//求两个参数的和

//先定义一个抽象的行为.

public int compute3(int a, int b, BiFunction biFunction) {

return biFunction.apply(a, b);

}

//BiFunction andThen

public int compute4(int a, int b, BiFunction biFunction, Function function) {

return biFunction.andThen(function).apply(a, b);

}

测试 函数式接口的实例:

public class PersonTest {

public static void main(String[] args) {

List personList = new ArrayList<>();

personList.add(new Person("zhangsan", 20));

personList.add(new Person("zhangsan", 28));

personList.add(new Person("lisi", 30));

personList.add(new Person("wangwu", 40));

PersonTest test = new PersonTest();

//测试 getPersonUsername

// List personList1 = test.getPersonUsername("zhangsan", personList);

// personList1.forEach(person -> System.out.println(person.getUsername()));

//测试 getPersonByAge

List personByAge = test.getPersonByAge(25, personList);

personByAge.forEach(person -> System.out.println(person.getAge()));

//测试第三种: 自定义输入行为

List list = test.getPersonByAge2(20,personList,(age,persons) ->{

return persons.stream().filter(person -> person.getAge() > age).collect(Collectors.toList());

});

list.forEach(person -> System.out.println(person.getAge()));

}

public List getPersonUsername(String username, List personList) {

return personList.stream().filter(person -> person.getUsername().equals(username)).collect(Collectors.toList());

}

public List getPersonByAge(int age, List personList) {

//使用BiFunction的方式

// BiFunction, List> biFunction = (ageOfPerson, list) -> {

// return list.stream().filter(person -> person.getAge() > ageOfPerson ).collect(Collectors.toList());

// };

//变换之后:

BiFunction, List> biFunction = (ageOfPerson, list) ->

list.stream().filter(person -> person.getAge() > ageOfPerson ).collect(Collectors.toList());

return biFunction.apply(age, personList);

}

//第三种方式, 动作也让用户自己定义传进来

public List getPersonByAge2(int age ,List list,BiFunction,List> biFunction){

return biFunction.apply(age, list);

}

}

函数式接口的真谛: 传递的是行为,而不是数据。

public static void main(String[] args) {

//给定一个输入参数,判断是否满足条件,满足的话返回true

Predicate predicate = p -> p.length() > 5;

System.out.println(predicate.test("nnihaoda"));

}

到现在为止,只是讲解了Java.lang.function包下的几个最重要的,经常使用的方法。

2020年1月3日08:06:28

BinaryOperator 接口

public class SinaryOpertorTest {

public static void main(String[] args) {

SinaryOpertorTest sinaryOpertorTest = new SinaryOpertorTest();

System.out.println(sinaryOpertorTest.compute(1,2,(a,b) -> a+b));

System.out.println("-- -- - - - -- -");

System.out.println(sinaryOpertorTest.getMax("hello123","world",(a,b) -> a.length() - b.length()));

}

private int compute(int a, int b, BinaryOperator binaryOperator) {

return binaryOperator.apply(a, b);

}

private String getMax(String a, String b, Comparator comparator) {

return BinaryOperator.maxBy(comparator).apply(a, b);

}

}

Optional final :Optional 不要试图用来当做参数, 一般只用来接收返回值,来规避值的空指针异常的问题。

empty()

of()

ofNullable()

isPresent()

get()

...

public class OptionalTest {

public static void main(String[] args) {

Optional optional = Optional.of("hello");

//不确定是否为 空是 调用和这个方法

// Optional optional2 = Optional.ofNullable("hello");

// Optional optional1 = Optional.empty();

//过时

// if (optional.isPresent()) {

// System.out.println(optional.get());

// }

optional.ifPresent(item -> System.out.println(item));

System.out.println(optional.orElse("nihao"));

System.out.println(optional.orElseGet(() -> "nihao"));

}

public class OptionalTest2 {

public static void main(String[] args) {

Employee employee = new Employee();

employee.setName("dawa");

Employee employee1 = new Employee();

employee1.setName("erwa");

List list = Arrays.asList(employee, employee1);

Company company = new Company("gongsi", list);

Optional optionalCompany = Optional.ofNullable(company);

System.out.println(optionalCompany.map(company1 -> company1.getList()).orElse(Collections.emptyList()));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值