JAVA8实战 -- Lamdba表达式

JAVA8实战

文章目录

  • JAVA8实战
  • 前言
  • 一、JAVA8的核心和优势是什么
  • 二、Lambda表达式
    • 1.函数式编程 -- 将代码传递给方法(将方法作为参数传递给另外一个代码)
    • 2.Lambda表达式 (匿名函数)
    • 3.JAVA8 已定义的函数式接口
    • 4、自定义函数式接口
    • 5、对设计模式的优化


前言

一直在使用JAVA8,但是没有系统的学习过JAVA8,也是一知半解,入手JAVA8实战,系统的了解和学习JAVA8的内容。
书籍:《JAVA8实战》
视频:https://www.bilibili.com/video/BV1VW41127sh?spm_id_from=333.337.search-card.all.click&vd_source=fce799ae483f16799f55fcb9708668ff

一、JAVA8的核心和优势是什么

(1)多核处理大型数据集
(2)函数式编程更适应新的体系架构
因此,核心特性为:Lambda、流、默认方法

二、Lambda表达式

1.函数式编程 – 将代码传递给方法(将方法作为参数传递给另外一个代码)

下面的代码是获取当前目录隐藏文件和目录的方法,可以看到JAVA8的实现,(1)代码量少,(2)内存少(不再使用内部类,占用内存会变少)

        File[] hiddenFiles = new File("./").listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isHidden();
            }
        });
        
        File[] hiddenFilesJav8 = new File("./").listFiles(File::isHidden);

JAVA8引入了::语法,即把这个值作为函数,那么将方法传递给方法又是如何做到的呢?肯定是有一个东东是可以接收方法的,JAVA8使用Predictate和Function实现,例如下面的代码,其中Predicate就是谓词方式,即给定一个T,返回一个boolean值,true或者false,JAVA8也会允许你写Function的形式,即给定一个T,返回一个E。

package com.example.demo.guava;


import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Administrator
 * @since 2022/9/6 22:39
 */
@Data
class Apple {
    private String green;
    private Integer weight;

    public static boolean isGreenApple(Apple apple) {
        return StringUtils.equals("green", apple.getGreen());
    }

    public static boolean isHeavyApple(Apple apple) {
        return 50 < apple.getWeight();
    }
}

public class FunctionalTest {


    public interface Predicate<T> {
        boolean test(T t);
    }

    static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
        List<Apple> result = new ArrayList<>();
        for (Apple apple : inventory) {
            if (p.test(apple)) {
                result.add(apple);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        List<Apple> inventory = new ArrayList<>();
        filterApples(inventory, Apple::isGreenApple);
        filterApples(inventory, Apple::isHeavyApple);
    }

}

那么,第一个案例又是使用的哪个呢?
File的listFiles()参数时FileFilter,是一个函数式接口,入参是File,返回的是一个boolean,正好File的isHidden入参是File,返回是boolean,实现了此方法的调用。
JAVA8实战 -- Lamdba表达式_第1张图片

2.Lambda表达式 (匿名函数)

上面的方法虽然实现了函数的传递,但是仍然需要定义函数,那有没有简便的写法呢,即lambda的方法了(匿名函数)。

        filterApples(inventory, apple -> StringUtils.equals("green", apple.getGreen()));
        filterApples(inventory, apple -> 50 < apple.getWeight());

lambda的语法糖方法引用 ::
都哪些方法可以使用方法引用呢:
(1)静态方法

        List<String> tmp = Arrays.asList("1", "3", "5");
        tmp.forEach(Integer::parseInt);;

JAVA8实战 -- Lamdba表达式_第2张图片
(2)实例方法String::length
JAVA8实战 -- Lamdba表达式_第3张图片
(3)无参构造函数 Apple::new

3.JAVA8 已定义的函数式接口

1.Predictate函数式接口
给定一个参数,方法是返回一个boolean,即当方法使用的是Predicate参数时,即可以使用Predicate的函数式接口了。
JAVA8实战 -- Lamdba表达式_第4张图片
可以使用举例:
ArrayList的方法:
JAVA8实战 -- Lamdba表达式_第5张图片
JAVA8实战 -- Lamdba表达式_第6张图片
Predict有很多其它的方法,比如and、or、not、

        Predicate predicate1 = o1->StringUtils.equals("李天一","李天二");
        Predicate predicate2 = o1->StringUtils.equals("李天一","李天一");
        aservice.sout(predicate1.or(predicate2)); // 官二代

自定义方法,支持Predicate的函数式接口,直接参数设置成Predicate即可。

@Data
@AllArgsConstructor
public class AService {

    private String name;

    public void sout(Predicate predicate) {
        if (predicate.test(name)) {
            System.out.println("官二代");
        } else {
            System.out.println("寒门");
            ;
        }
    }
}

单测代码:
    private AService aservice = new AService("李天一");

    @Test
    public void testSout() throws Exception {
        aservice.sout(o1-> StringUtils.equals(aservice.getName(),"李天一"));
    }

2.Consumer接口
Consumer接口是消费型接口,对一个给定对象直接处理。
JAVA8实战 -- Lamdba表达式_第7张图片
Comsumer还有一个接口,是andThen(),即先执行一个消费方法,再执行一个消费方法

        Consumer consumer1 = o1->System.out.println("李天一");
        Consumer consumer2 = o1->System.out.println("李天二");
        aservice.compare(consumer1.andThen(consumer2)); // 李天一  李天二

自定义Consumer

    public void compare(Consumer consumer){
        consumer.accept(name);
    }
单测

    @Test
    public void testConsumer() throws Exception{
        aservice.compare(o1-> System.out.println(aservice.getName()));
    }

最常使用的是Collection接口的foreach函数
3.Function接口
Function接口是给定两个参数,返回一个参数的方法。同样有一些组合Function,compose(组合) 、andThen(然后)、identify()
JAVA8实战 -- Lamdba表达式_第8张图片
抄袭一个大神的代码,compose是先执行的,andThen是后执行的

        Function<Integer, Integer> times2 = i -> i*2;
        Function<Integer, Integer> squared = i -> i*i;
        
        System.out.println(times2.apply(4));
        
        System.out.println(squared.apply(4));
        
		//32                先4×4然后16×2,先执行apply(4),在times2的apply(16),先执行参数,再执行调用者。
        System.out.println(times2.compose(squared).apply(4));  
        
        //64               先4×2,然后8×8,先执行times2的函数,在执行squared的函数。
        System.out.println(times2.andThen(squared).apply(4));  
        
		 //16
        System.out.println(Function.identity().compose(squared).apply(4)); 

4、自定义函数式接口

函数式接口就是只有一个函数的接口,可以添加@FunctionalInterface对于编译器编译提示。

public interface OrderService {
    void saveOrder();
}

或者

@FunctionalInterface
public interface OrderService {
    void saveOrder();
}

5、对设计模式的优化

持续优化中

总结
整体梳理了一下JAVA8 Lamdba的使用和函数式接口、自定义函数式接口,对设计模式的优化需要持续学习。

你可能感兴趣的:(JAVA基础,java,jvm,开发语言)