2021-07-26


Lambda表达式、函数式接口

1. Lambda
1.1 概述
Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。
本质上是一段匿名内部类,也可以是一段可以传递的代码。
还有叫箭头函数的…

1.2 优点
是匿名内部类的简写方式,使代码更加简洁

1.3 和匿名内部类对比
public class Lambda_01 {
    public static void main(String[] args) {
        String[] strs = { "12", "2", "123", "1" };
        // 转换为list
        List<String> strings = Arrays.asList(strs);
        // 箭头函数
        Collections.sort(strings, (s1, s2) -> {
            Integer i1 = Integer.valueOf(s1);
            Integer i2 = Integer.valueOf(s2);
            return i2 - i1;
        });
        System.out.println(strings);

1.4 语法结构
(参数,参数,参数…) -> {方法体}

1 无参和多参,小括号必须写
2 只有一个参数的时候,小括号可以不写
3 如果只有一条语句,大括号也可以不写,并且语句结尾不需要 分号
4 如果只有一条语句,并且也是返回值语句的话,return 也要省略
5 如果是多条语句,必须加{},就是正常编码,该写分号写分号,该写return就写return

1.5 案例
public class Lambda_02 {
    public static void main(String[] args) {
        Integer[] is = { 1, 4, 5, 2, 3, 7 };
        List<Integer> list = Arrays.asList(is);
        // 方法体里只有一个return的省去大括号,省去return ;
        Collections.sort(list, (x, y) -> y - x);
        System.out.println(list);
    }
}

1
2
3
4
5
6
7
8
9
10
2. 函数式接口
2.1 概述
英文称为Functional Interface

其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。

其可以被隐式转换为 lambda 表达式。

2.2 特点
函数式接口是仅制定一个抽象方法的接口

可以包含一个或多个静态或默认方法

专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用

2.3 自定义
// 可以加也可以不加
// 函数式接口中,只允许出现一个 抽象方法 ,和N个非抽象方法
// 可以有别的static default方法
@FunctionalInterface
interface MyFunction {
    public void print();
}

public static void main(String[] args) {
        // 子实现类的写法
        Test test = new Test();
        m1(test);
        // 匿名内部类
        m1(new MyFunction() {

            @Override
            public void print() {
                System.out.println("匿名内部类");
            }
        });
        // 箭头函数
        m1(() -> System.out.println("lambda表达式写法"));
    }

2.4 JDK自带的函数式接口
Supplier : 表示供应商,有个get方法,无参,有返回值,一般用于获取数据
Consumer : 表示消费者,accept,有参,无返回值
Function ,函数操作, apply , 有参也有返回值
Predicate 断言,用于做判断校验操作,test,需要传入参数并返回boolean类型

3. 方法、构造器、数组
3.1 概述
Lambda表达式的另外一种形式

3.2 方法引用
对象引用 :: 成员方法名
public static void main(String[] args) {
        Integer i1 = 12;
        i1.toString();
        Supplier<String> supplier = i1::toString;
        System.out.println(supplier.get());
        System.out.println(i1.toString());
    }

类名 :: 静态方法名
public static void main(String[] args) {
        String string = "123";
        Function<String, Integer> function = Integer::parseInt;
        int value = function.apply(string);
        System.out.println(value);
    }

类名 :: 成员方法名
public static void main(String[] args) {
        BiPredicate<String, String> predicate = String::equals;
        System.out.println(predicate.test("a", "'b"));
    }
1
2
3
4
5
3.3 构造器引用
public static void main(String[] args) {
        // 无参构造
        Supplier<Object> s1 = Object::new;
        System.out.println(s1.get());
        // 有参构造
        Function<String, String> f1 = String::new;
        System.out.println(f1.apply("zxc"));
    }

3.4 数组引用
public static void main(String[] args) {
        // 泛型第一个是长度,第二个是返回值
        Function<Integer, Integer[]> fun = Integer[]::new;
        Integer[] arr = fun.apply(4);
        for (Integer integer : arr) {
            System.out.println(integer);
        }
    }
 API
4.1 概述
数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。
1
集合讲的是数据,流讲的是计算

即一组用来处理数组,集合的API。

4.2 特点
Stream 不是数据结构,没有内部存储,自己不会存储元素。

Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

不支持索引访问。

延迟计算

支持并行

很容易生成数据或集合

支持过滤,查找,转换,汇总,聚合等操作。

4.3 应用场景
流式计算处理,需要延迟计算、更方便的并行计算

更灵活、简洁的集合处理方式场景

4.4 创建流的五种方式
public static void main(String[] args) {
        // 1 数组
        String[] strings = { "a", "b", "c", "d" };
        Stream<String> stream1 = Stream.of(strings);

        // 2 通过集合
        List<String> strings2 = Arrays.asList(strings);
        Stream<String> stream2 = strings2.stream();

        // 3 通过Stream.generate来创建
        // 创建一个无限流,里面全是1,并且通过limit限制条数是5条
        Stream<Integer> generate = Stream.generate(() -> 1);
        generate.limit(5).forEach(x -> System.out.println(x));

        // 4 通过Stream.iterate来创建
        // 创建一个无限流,里面的数据有序,从2开始步长为3
        Stream<Integer> iterate = Stream.iterate(2, x -> x + 3);
        iterate.limit(5).forEach(x -> System.out.println(x));

        // 5 通过已有API
        String string = "abc";
        IntStream chars = string.chars();
        chars.forEach(x -> System.out.println(x));
    }

4.5 转换算子
4.5.1 概述
转换算子,又称为中间操作,所有的转换算子得到的都是一个新的流,所以一般用于链式调用
常用的转换算子
limit:取集合中的前几条数据
filter:对元素进行过滤筛选
distinct:去除重复
skip:跳过
map:更改数据
sorted:排序
注意:只有转换算子是不执行,必须执行动作算子才会真正执行
4.5.2 常用方法
public static void main(String[] args) {
        // 只要a
        List<String> strings = Arrays.asList("a", "b", "c", "a");
        Stream<String> stream = strings.stream();
        // collect动作算子,把流中的数据转换为集合
        // filter不符合条件的就不要了,返回false就是不要,true就是要
        List<String> value = stream.filter(x -> x.equals("a")).collect(Collectors.toList());
        System.out.println(value);
        // 不要偶数
        // 拿到一个集合用流过滤
        List<Integer> integers = Arrays.asList(1, 3, 5, 6, 8, 9, 11, 144, 25, 257);
        Stream<Integer> stream1 = integers.stream();
        List<Integer> value2 = stream1.filter(x -> x % 2 == 1).collect(Collectors.toList());
        System.out.println(value2);

        // skip:跳过元素
        stream1 = integers.stream();
        value2 = stream1.skip(2).collect(Collectors.toList());
        System.out.println(value2);

        // distinct:去重
        stream = strings.stream();
        value = stream.distinct().collect(Collectors.toList());
        System.out.println(value);

        // map:遍历过程中对元素进行操作,比如涨薪
        List<Double> sal = Arrays.asList(1122.2, 2000.5, 8888.8);
        Stream<Double> salStream = sal.stream();
        List<Double> newSal = salStream.map(x -> x * 10).collect(Collectors.toList());
        System.out.println(newSal);

        // limit 前几条,比如查看前两名
        salStream = sal.stream();
        // sorted进行排序
        newSal = salStream.sorted((x, y) -> {
            if (y > x) {
                return 1;
            } else if (y == x) {
                return 0;
            } else {
                return -1;
            }
        }).limit(2).collect(Collectors.toList());
        System.out.println(newSal);
    }

4.6 动作算子
public class Stream_03 {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("a", "b", "c", "a", "b", "c", "a");
        Stream<String> stream = strings.stream();
        // foreach遍历操作
        stream.forEach(x -> System.out.println(x));

        // 技术 count
        stream = strings.stream();
        long count = stream.filter(x -> x.equals("a")).count();
        System.out.println(count);

        // max获取最大值
        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
        Stream<Integer> integerStream = integers.stream();
        Integer i1 = integerStream.max((x, y) -> x - y).get();
        System.out.println(i1);

        // anyMatch匹配数据,比如是否包含
        integerStream = integers.stream();
        boolean flag = integerStream.anyMatch(x -> x == 5);
        System.out.println(flag);
        // 当然这种是否包含可以使用contains解决,但是有的是contains解决不了的
        System.out.println(integers.contains(5));

        // 比如 所有的用户中是否有19岁的
        List<User> users = new ArrayList<User>();
        users.add(new User("a", 18));
        users.add(new User("b", 19));
        users.add(new User("c", 20));
        Stream<User> userStream = users.stream();
        flag = userStream.anyMatch(u -> u.age == 19);
        System.out.println(flag);
    }
}

class User {
    String name;

    int age;

    public User(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值