java-Lambda表达式

一、概念

  • 引入lambda原因:就是为了简化代码,封装我们的操作,所以引入了函数式接口的概念
  • 是什么:接口的匿名实现
  • 组成:参数列表、方法体、运算符
(str)->{System.out.println(str);}

二、基础语法

1.使用Lambda表达式的前提

  • 接口中仅有一个抽象方法(可以有static方法和default方法,但是抽象方法只能有一个,抽象方法只能有一个)
  • 为了防止接口中有多个抽象方法,可以在接口上添加@FunctionalInterface注解,有多个抽象方法就会产生警告

2.简化

  • 接口
public interface LambdaIns {
    public abstract String test01();
}

interface LambdaIns02 {
    String test02(String str);
}

interface LambdaIns03 {
    void test03();
}

interface LambdaIns04 {
    void test04(String str);
}
  • 使用Lambda

(1)可以省略参数列表的括号:当只有一个参数的时候,参数列表可以省略括号

(2)不可以省略参数列表的括号:没有参数或者有多个参数

(3)可以省略大括号:

①没有返回值,方法体只有一行代码

②有返回值,方法体只有一行代码,省略大括号同时需要省略return

public class LambdaInsImp{

    public static void main(String[] args) {
        // 1.有返回值,没参数
        LambdaIns lambdaIns01 = () ->{
          return "test01";
        };
        // 有返回值,没参数(简化)
        LambdaIns lambdaIns01Simplify = () -> "test01";
        System.out.println(lambdaIns01Simplify.test01());


        // 2.有返回值,有参数
        LambdaIns02 lambdaIns02 = (str) -> {
            return str;
        };
        // 有返回值,有参数(简化)
        LambdaIns02 lambdaIns02Simplify = str -> str;
        System.out.println(lambdaIns02Simplify.test02("test02"));

        // 3.没返回值没参数
        LambdaIns03 lambdaIns03 = () -> {
            System.out.println("test03");
        };
        // 没返回值没参数(简化)
        LambdaIns03 lambdaIns03Simplify = () -> System.out.println("test03");
        lambdaIns03.test03();

        // 4.没返回值有参数
        LambdaIns04 lambdaIns04 = (str) -> {
            System.out.println(str);
        };
        // 没返回值有参数(简化)
        LambdaIns04 lambdaIns04Simplify = str -> System.out.println(str);
        lambdaIns04Simplify.test04("test04");
    }

}

三、函数式接口

  • java.util.function包下的核心接口Function、Supplier、Consumer、Predicate

1.Function函数型接口

该接口中apply是核心,所有其他的方法体都再调用apply方法,重点是有返回值,再使用表达式的时候注意返回值

(1)源码解读

/**
 * 表示接受一个参数并生产一个结果的函数
 * @param <T> 函数的输入类型
 * @param <R> 函数的输出类型
 * @since 1.8
 */
@FunctionalInterface
public interface Function<T, R> {

    /**
     * 应用这个方法可以生产一个参数
     */
    R apply(T t);

    /**
     *该函数先执行参数,再执行调用者
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * 该函数先执行调用者,再执行参数
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * 该函数调用者是什么类型就返回什么类型
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

(2)案例

    public static void main(String[] args) {
        Function<Integer,Integer> A= i->i+1;
        Function<Integer,Integer> B=i->i*i;
        // 先执行A再执行B,结果36
        System.out.println("F1:"+B.compose(A).apply(5));
        // 先执行B再执行A,结果26
        System.out.println("F2:"+B.andThen(A).apply(5));
    }

2.Consumer消费型接口

重点:没有返回值

(1)源码解读

/**
 * 代表了接受一个输入参数并且无返回的操作,相当于消费者
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {

    /**
     * 对参数进行消费
     */
    void accept(T t);

    /**
     * 按顺序组合调用者对参数进行消费
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

(2)案例

    public static void consumerTest(String[] strArr, Consumer<String> con1, Consumer<String> con2, Consumer<String> con3){
        for(int i = 0; i < strArr.length; i ++){
            con1.andThen(con2).andThen(con3).accept(strArr[i]);
        }
    }

    public static void main(String[] args) {
        String[] strArr = {"刘志,男,18","静心,男,19","净心,男,20"};
        consumerTest(strArr,t -> {
            t.split(",");
            System.out.print(t.split(",")[0] + "。");
        },t -> {
            System.out.print(t.split(",")[1] + "。");
        },t -> {
            System.out.println(t.split(",")[2] + "。");
        });
    }

输出结果:
刘志。男。18。
静心。男。19。
净心。男。20。

3.Supplier供给型接口

(1)源码解读

/**
 * 供给型接口
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    T get();
}

(2)案例

    public static void main(String[] args) {
        Employee employee = new Employee();
        employee.setId(1);
        employee.setName("静心");
        Supplier<String> supplier = employee::getName;
        System.out.println(supplier.get());
        Supplier<Employee> supplier02 = () -> employee;
        System.out.println(supplier02.get());
    }
输出:
静心
Employee{id=1, name='静心', age=18}

4.Predicate 断言型接口

(1)源码解读

/**
 * 接收一个参数,返回一个布尔值,用来进行判断是否符合条件
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * 评估参数里的表达式
     * 具体过滤操作 需要被子类实现.
     * 用来处理参数T是否满足要求
     */
    boolean test(T t);

    /**
     * 调用当前Predicate的test方法之后再去调用other的test方法,相当于进行两次判断
     * 可理解为 条件A && 条件B
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * 对当前判断进行"!"操作,即取非操作 !A
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * 对当前判断进行"||"操作,即取或操作,可以理解为 条件A ||条件B
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * 对当前操作进行"="操作,即取等操作,可以理解为 A == B
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

(2)案例

    public static void main(String[] args) {
        // 1、判断数字是否大于7,设置一个大于7的过滤条件
        Predicate<Integer> predicate = x -> x > 5;
        System.out.println(predicate.test(6));
        System.out.println(predicate.test(4));

        // 2 &&、大于5并且,在上面大于7的条件下,添加是偶数的条件
        predicate = predicate.and(x -> x % 2 == 0);
        System.out.println(predicate.test(4));
        System.out.println(predicate.test(6));
        System.out.println(predicate.test(3));

        // 3、! 取反: x > 5的取反
        Predicate<Integer> predicate2 = x -> x < 5;
        Predicate<Integer> negate = predicate2.negate();
        System.out.println(negate.test(6));

        // 4. || 或:x小于5或者x是奇数
        Predicate<Integer> predicate3 = x -> x < 5;
        predicate3 = predicate3.or(x -> x % 2 == 1);
        System.out.println(predicate3.test(4));
    }

四、方法引用

前置条件

class Employee{

    private Integer id;
    private String name;
    private Integer age;

    public Employee() {
    }

    public Employee(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

1、对象实例方法名

Employee employee = new Employee();
employee.setId(1);
employee.setName("静心");
employee.setAge(18);
Supplier<String> supplier = employee::getName;

2、类::静态方法名

Comparator<Integer> com = Integer::compare;

3、类::实例方法名

Comparator<String> com = String :: compareTo;

4、构造器使用

Supplier<Employee> sup = Employee::new;

5、数组引用

Function<Integer,String[]> fun = String[]::new;

五、Stream API

1.概念

对集合进行处理,例如查询,过滤,映射等操作,类似于sql

2.注意

  • Stream本身并不存储数据
  • Stream对集合的操作,并不会改变源数据,而是返回新的stream
  • Stream操作是延迟执行的,等到需要结果的时候才执行

3.Stream操作的步骤

  • 创建:从数据源(集合,数组)中获取stream
  • 中间操作:对集合进行一系列的中间操作(过滤,映射等),对数据源进行处理
  • 终止操作:执行中间操作完毕之后并产生结果,终止操作执行之后不能再对stream进行操作

4.创建Stream

(1)可以通过Collection系列集合提供的stream()或parallelStream()方法创建流

//返回顺序流,和集合顺序一致
Stream<String> stream1 = list.stream();
//返回并行流,并行取数据,和集合顺序不一致
Stream<String> stream2 = list.parallelStream();

(2)通过Arraya的静态方法stream()获取数组流

Stream<Employee> stream = Arrays.stream(emps);

(3)通过Stream的静态方法of()显示的创建一个流,可以接受任何数量的参数

Stream<String> stream1=Stream.of("aa","bb","cc");

(4)使用Stream.iterate()和Stream.generate(),创建无限流

//迭代(遍历前10个偶数)
Stream<Integer> stream1=Stream.iterate(0, x -> x+2);
//limit中间操作;forEach终止操作
stream1.limit(10).forEach(System.out::println);
//生成前5个随机数
Stream.generate(Math::random).limit(5).forEach(System.out::println);

5.中间操作

(1)筛选与切片

①filter(Predicate p):从流中排除某些元素

empList.stream().filter(e -> e.getAge() > 18).forEach(System.out::println);

②limit:limit(n)--截断流,使其元素不超过给定数量。

empList.stream().limit(5).forEach(System.out::println);

③skip:skip(n)--跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n) 互补,从0开始,左开右闭

empList.stream().skip(0).limit(10).forEach(System.out::println);// 从0开始,不包括0,向后截取10条数据

④distinct:筛选,通过元素的 hashCode() 和 equals() 去掉重复元素(对于自定义的类,需要实现这两个方法)

empList.stream().distinct().collect(Collectors.toList()).forEach(System.out::println);

⑤map(Function f)--映射。接收Lambda,将每个元素转换成其他形式或提取信息

empList.stream().map(e -> e.getName().toUpperCase()).forEach(System.out::println);

⑥mapToInt:

List<String> list = Arrays.asList("3", "6", "8", "14", "15");
list.stream().mapToInt(num -> Integer.parseInt(num)).filter(num -> num % 3 == 0).forEach(System.out::println);

⑦mapToLong

用法类似同上

⑧mapToDouble

用法类似同上

⑨peek:文档上说peek主要被用在debug用途,peek和map的用法类似,但是peek接受的是Consumer,而map接受的是Function,Consumer没有返回值,而Function有返回值

    /**
     * 过年之后员工的年纪长一岁,性别为M的换成male,为F的换成female
     */
    public static List<EmployeeList> addEmployeeAge01(){
        List<EmployeeList> employeeList = EmployeeList.getEmployee();
        List<EmployeeList> eList = employeeList.stream().map(
                e -> {
                    e.setAge(e.getAge() + 1);
                    e.setSex(e.getSex().equals("M") ? "male" : "female");
                    return e;
                }
        ).collect(Collectors.toList());
        return eList;
    }

    /**
     * map替换成peek
     * @param
     */
    public static List<EmployeeList> addEmployeeAge02(){
        List<EmployeeList> employeeList = EmployeeList.getEmployee();
        // 当List期望的结果泛型对象和参数对象一致时可以将map替换成peek,并且可以去掉return
        List<EmployeeList> eList = employeeList.stream().peek(
                e -> {
                    e.setAge(e.getAge() + 1);
                    e.setSex(e.getSex().equals("M") ? "male" : "female");
                }
        ).collect(Collectors.toList());
        return eList;
    }

⑨flatMap:把多个小list转化为一个大list

        List<String> a = Arrays.asList("1", "2", "3");
        List<String> b = Arrays.asList("4", "5", "6");
        List<String> c = Arrays.asList("7", "8", "9");
        List<String> d = Arrays.asList("10", "11", "12");
        List<String> e = Arrays.asList("13", "14", "15");
        List<String> f = Arrays.asList("16", "17", "18");
        List<String> g = Arrays.asList("19", "20", "21");
        List<String> h = Arrays.asList("22", "23", "24");

        List<List<String>> numberAlllist = new ArrayList<>();
        numberAlllist.add(a);
        numberAlllist.add(b);
        numberAlllist.add(c);
        numberAlllist.add(d);
        numberAlllist.add(e);
        numberAlllist.add(f);
        numberAlllist.add(g);
        numberAlllist.add(h);

        // 使用普通方式
        List<String> listOfAllPlayers = new ArrayList<>();
        for(List<String> team : numberAlllist){
            for(String name : team){
                listOfAllPlayers.add(name);
            }
        }
        System.out.println(listOfAllPlayers);
        // Lambda表达式方式
        List<String> finalList = numberAlllist.stream().flatMap(pList -> pList.stream()).collect(Collectors.toList());
        System.out.println(finalList);

flatMapToInt

和上面类似

flatMapToLong

和上面类似

flatMapToDouble

和上面类似

⑩sorted:排序

// 对基本类型进行排序
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(0);
intList.add(4);
intList.add(3);
intList.add(10);
intList.add(99);
intList.add(21);
intList.stream().sorted().forEach(System.out::println);// 升序
intList.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println); //倒叙

// 对对象进行排序
class Employee{

    private Integer id;
    private String name;
    private Integer age;

    public Employee() {
    }

    public Employee(Integer age, String name) {
        this.name = name;
        this.age = age;
    }

    public Employee(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
Employee e1 = new Employee();
e1.setId(1);
e1.setName("净法");
e1.setAge(18);
Employee e2 = new Employee();
e2.setId(2);
e2.setName("净宽");
e2.setAge(20);
Employee e3 = new Employee();
e3.setId(3);
e3.setName("净宽");
e3.setAge(23);
List<Employee> list = new LinkedList<Employee>();
list.add(e1);
list.add(e2);
list.add(e3);
list.stream().sorted(Comparator.comparing(Employee::getAge).reversed()).forEach(System.out::println);

(2)终止操作

①anyMatch

allMatch

noneMatch

// 检查是否所有的age都大于18的
boolean b = empList.stream().allMatch(e -> e.getAge() > 18);
// 检查是否有age大于18的
boolean b1 = empList.stream().anyMatch(e -> e.getAge() > 18);
// 检查是否没有age大于18的
boolean b2 = empList.stream().noneMatch(e -> e.getAge() > 18);

②findFirst

findAny

Optional<Employee> first = list.stream().findFirst();
Optional<Employee> any = list.stream().findAny();

③reduce:Stream.reduce()合并流的元素并产生单个值

// 方法签名:T reduce(T identity, BinaryOperator<T> accumulator);
// identity:默认值或初始值。
// accumulator:函数式接口,取两个值并产生一个新值
// 案例
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sum = Arrays.stream(numbers).reduce(0, (a, b) -> a + b);
System.out.println("sum : " + sum); // 55

更多运算:https://blog.csdn.net/qq_39175358/article/details/114387328

④collect:配合Collectors类的静态方法,将流转换为其他数据类型(如List、Set、Map)

        List<String> list = listDeal.stream().map(Employee::getName).collect(Collectors.toList());
        System.out.println(list);
        // (5)set
        Set set = listDeal.stream().map(Employee::getName).collect(Collectors.toSet());
        System.out.println(set);

        // (6)map
        Map<Integer, Employee> map = listDeal.stream().collect(Collectors.toMap(Employee::getId, e -> e));
        map.forEach((key, value) -> {
            System.out.println(key + ":" + value);
        });

⑤min:

// 求年龄最大的员工(此处使用的是Stream中的max)        
Employee employee = listDeal.stream().max(Comparator.comparing(Employee::getAge)).get();
// 求员工的最大年龄(此处使用的是IntStream中的max)
int asInt = listDeal.stream().mapToInt(Employee::getAge).max().getAsInt();

max:用法同上

⑥forEach

empList.stream().skip(0).limit(10).forEach(System.out::println);

⑦toArray

        String[] strings = listDeal.stream().map(Employee::getName).toArray(String[]::new);
        for (String string : strings) {
            System.out.println(string);
        }

        Employee[] employees = listDeal.stream().toArray(Employee[]::new);
        for (Employee employee : employees) {
            System.out.println(employee);
        }

⑧count

// 计算流中元素的个数
long count = listDeal.stream().count();

⑨empty:流empty()返回空的顺序流

Stream stream = Stream.empty();

⑩of:返回包含单个指定元素的顺序Stream

        Stream stream = Stream.of("Geeks", "for", "Geeks"); 
        stream.forEach(System.out::println); 

⑪iterate

Stream.iterate(0, x -> x + 2).limit(10).forEach(System.out::println);

⑫generate

        // 生成5个随机数
        Stream.generate(Math::random).limit(5).forEach(System.out::println);

⑬concat:流的合并

        String[] stringArr = {"meiyangyang","xiyangang","lanyangyang"};
        Integer[] integers = {1,2,3};
        Stream stream = Stream.of(stringArr);
        Stream stream1 = Stream.of(integers);
        Stream stream2 = Stream.concat(stream,stream1);
        stream2.forEach(s->System.out.println(s));

六、Optional

1、概念

Optional 类主要解决的问题是臭名昭著的空指针异常,Optional 类既可以含有对象也可以为空

2.创建一个空的 Optional

// 如果输出System.out.println(emptyOpt.get());会显示NoSuchElementException
Optional<User> emptyOpt = Optional.empty();

3.of() 和 ofNullable() 

// 两者主要的区别就是,of穿null会报空指针异常,ofNullable则不会,而是返回Optional.empty
Optional<Employee> value = Optional.ofNullable(null);
Optional<Employee> value2 = Optional.of(null);

4.get():Optional获取返回的实际对象需要使用get()方法


        Optional<Employee> optionalEmployee = Optional.ofNullable(e1);
        // 不使用get返回的对象是这样的 Optional[Employee{id=1, name='净法', age=18, score='99.5'}]
        System.out.println(optionalEmployee);
        // 使用get返回的结果 Employee{id=1, name='净法', age=18, score='99.5'}
        System.out.println(optionalEmployee.get());
        
  • 注意:当参数为null的时候,使用get方法会返回NoSuchElementException异常

5.isPresent():判断当前是否有值

// 有值返回true,没有值返回false
System.out.println(optionalEmployee.isPresent());

6.ifPresent(Consumer<? super T> consumer):进行对象操作,存在则操作,否则不操作

        // 如果是对象(引用类型),则ifPresent会改变对象
        User user = new User();
        user.setId(1);
        user.setName("静心");
        user.setAge(17);
        Optional.ofNullable(user)
                .ifPresent(u -> {
                    u.setAge(u.getAge() + 1);
                });
        System.out.println(user);// 输出User{id=1, name='静心', age=18}
        // 如果是值类型,不改变原变量
        int i = 1;
        Optional.ofNullable(i).ifPresent(t -> {
            t = t + 1;
        });
        System.out.println(i);

7.orElse和orElseGet() 

        public static Employee getEmployee(){
            return (Employee) Study01.buildList().get(1);
        }        
        // orElse():如果有值返回原本的参数,如果为null则返回默认值(orElse()中的参数)
        Employee employee1 = listDeal.get(2);
        Employee employee2 = listDeal.get(0);
        Employee employee4 = Optional.ofNullable(employee1).orElseGet(() -> getEmployee());
        Employee employee3 = Optional.ofNullable(employee1).orElse(employee2);
        // 下面结果一样
        System.out.println(employee3);
        System.out.println(employee4);
        
  • 区别就是,当参数为null,默认的结果可以直接获取到则使用orElse,当默认的结果需要通过方法生成时则使用orElseGet()

8.orElseThrow(Supplier<? extends X> exceptionSupplier)

// 当employee1为null是可以自己选择返回的异常          
Employee result = Optional.ofNullable(employee1).orElseThrow( () -> new IllegalArgumentException());

9.Optional还有map,flatMap,filter方法,使用的方法和Stream中的相似

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SuperLBY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值