Java8 新特性 (Lambda表达式、Stream)

Lambda表达式

在这里插入图片描述
在这里插入图片描述
注意和Python中Lambda的区别,在Python中是方法,在Java中是对象。

在这里插入图片描述
在这里插入图片描述

无参,无返回值

 @Test
    public void test() {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("1");
            }
        };
        r1.run();

        System.out.println("*************");
        Runnable r2 = () -> System.out.println("2");
        r2.run();
    }

结果:
1
*************
2

有一个参数,无返回值

@Test
    public void test2() {
        Consumer<String> c1 = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        c1.accept("1");

        System.out.println("************");
        Consumer<String> c2 = (String s) -> {
            System.out.println(s);
        };
        c2.accept("2");
    }

结果:
1
************
2

数据类型可以省略 类型推断

在上面代码的基础上:

@Test
    public void test2() {
        Consumer<String> c1 = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        c1.accept("1");

        System.out.println("************");
        Consumer<String> c2 = (String s) -> {
            System.out.println(s);
        };
        c2.accept("2");
        System.out.println("********");

        Consumer<String> c3 = (s) -> {
            System.out.println(s);
        };
        c3.accept("3");
    }

结果:
1
************
2
********
3

下图也是类型推断:

在这里插入图片描述

若只有一个参数,参数的小括号可以省略

@Test
    public void test3() {

        Consumer<String> c3 = (s) -> {
            System.out.println(s);
        };
        c3.accept("1");
        System.out.println("*********");

        Consumer<String> c4 = s -> {
            System.out.println(s);
        };
        c4.accept("2");
    }

结果:
1
*********
2

两个参数,且方法体中可能有多条语句和返回值

@Test
    public void test4() {

        Comparator<Integer> c1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                return o1.compareTo(o2);
            }
        };
        System.out.println(c1.compare(15, 20));

        System.out.println("***********");
        Comparator<Integer> c2 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };

        System.out.println(c1.compare(25, 20));
    }

结果:
15
20
-1
***********
25
20
1

当Lambda体只有一条语句时,return与大括号若有,都可以省略

@Test
    public void test5() {
        Comparator<Integer> c1 = (o1, o2) -> {
            return o1.compareTo(o2);
        };
        System.out.println(c1.compare(25, 20));

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

        Comparator<Integer> c2 = (o1, o2) -> o1.compareTo(o2);
        System.out.println(c2.compare(20, 25));
    }

结果:
1
***********
-1

Lambda 总结

在这里插入图片描述

函数式接口

如果一个接口中只声明了一个抽象方法,则此接口称为函数式接口。
在这里插入图片描述

Lambda表达式只能用于接口中有一个抽象方法的情况,因此再实现抽象方法时就不必再指定方法名了,反正就那一个。也就是说Lambda表达式作为函数式接口的实例。

在这里插入图片描述

Consumer
 @Test
    public void test6() {
        shopping(1000, new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("购物共花费: " + aDouble);
            }
        });

        shopping(1500, money -> System.out.println("购物共花费: " + money) );
    }

    public void shopping(double money, Consumer<Double> con) {
        con.accept(money);
    }

结果:
购物共花费: 1000.0
购物共花费: 1500.0
Predicate

在这里插入图片描述
在这里插入图片描述

其他接口

在这里插入图片描述

方法引用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用举例

对象::非静态方法

在这里插入图片描述

在这里插入图片描述

类::静态方法

在这里插入图片描述
在这里插入图片描述

类::非静态方法

在这里插入图片描述
在这里插入图片描述

@Test
    public void test7() {
        Function<Person, String> f = new Function<Person, String>() {
            @Override
            public String apply(Person person) {
                return person.getName();
            }
        };
        System.out.println(f.apply(new Person("Li")));

        System.out.println("******");
        Function<Person, String> f2 = p -> p.getName();
        System.out.println(f2.apply(new Person("Wang")));

        System.out.println("******");
        Function<Person, String> f3 =Person :: getName;
        System.out.println(f3.apply(new Person("Zhao")));
    }

Li
******
Wang
******
Zhao

构造器引用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数组引用

在这里插入图片描述
在这里插入图片描述

Stream API

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Stream是延迟执行的,只有在需要结果的时候才会执行

创建Stream对象的方式

通过集合

在这里插入图片描述
在这里插入图片描述

通过数组

在这里插入图片描述

在这里插入图片描述

通过Stream的of()

在这里插入图片描述

在这里插入图片描述

无限流

在这里插入图片描述
在这里插入图片描述

中间操作

筛选与切片

在这里插入图片描述
再次注意,一旦对Stream执行了中止操作(forEach输出也算中止操作),后续的操作就无法执行了,因此下图会报错:

在这里插入图片描述

因此要重新生成一个stream,就像iterator那样:

在这里插入图片描述

在这里插入图片描述

映射

在这里插入图片描述

Map
 @Test
    public void test() {
        List<String> list = Arrays.asList("AA", "Bb", "aBc");
        list.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
        System.out.println(list);
    }

AA
BB
ABC
[AA, Bb, aBc]
flatmap

接收一个函数作为参数,将流中的每一个值换成另一个流,然后把所有流连接成一个流。

在这里插入图片描述

https://www.bilibili.com/video/BV1Kb411W75N?p=680

排序

在这里插入图片描述

sorted()

要想使用这个方法,相应的类需实现Comparable接口,排序后原集合不变。

调用sorted方法后会自动调用Integer的排序方法:

 @Test
    public void test() {
        List<Integer> list = Arrays.asList(18, 22, -1, 34, 14, 0);
        list.stream().sorted().forEach(x -> System.out.println(x));
        System.out.println(list);  // 验证排序后原list是否改变
    }

结果:
-1
0
14
18
22
34
[18, 22, -1, 34, 14, 0]

但要注意,如果我们想对对象列表进行排序,则相应的类要实现Comparable接口,或者使用另一种sorted()

sorted(Comparator com)

可以在sorted传入Comparator 实现类的对象以实现定制排序:

@Test
    public void test() {
        List<Integer> list = Arrays.asList(18, 22, -1, 34, 14, 0);
        
        list.stream().sorted(new Comparator<Integer>(){

            @Override
            public int compare(Integer o1, Integer o2) {
                return - o1.compareTo(o2);
            }
        }).forEach(System.out::println);
    }

结果:
34
22
18
14
0
-1

中止操作

在这里插入图片描述
在这里插入图片描述

匹配和查找
public class StopTest {
    @Test
    public void test1() {
        List<Integer> list = Arrays.asList(10, 5, -1, 32, 44, -11, 57);

        // allMatch 看看stream里面的元素是否都满足参数的条件
        boolean res = list.stream().allMatch(l -> l > -20);  // true
        System.out.println(res);

        // anyMatch stream里有一个满足参数的条件就行
        boolean res2 = list.stream().anyMatch(l -> l > 50); // true
        System.out.println(res2);

        // noneMatch 检查是否没有匹配的元素,若有则返回false
        boolean res3 = list.stream().noneMatch(e -> e.equals(5));  // false
        System.out.println(res3);

        // findfirst 返回第一个元素,注意返回值类型是Optional,后面会说
        Optional<Integer> res4 = list.stream().sorted().findFirst();  // Optional[-11]
        System.out.println(res4);

        // findAny 返回当前流中任意一个元素
        Optional<Integer> res5 = list.stream().findAny();  // Optional[10]
        System.out.println(res5);

        // count 返回流中元素的总个数
        long count = list.stream().count();  // 7
        System.out.println(count);

        // max 返回流中的最大值
//        Optional<Integer> max_num = list.stream().max(new Comparator<Integer>() {
//            @Override
//            public int compare(Integer o1, Integer o2) {
//                return o1.compareTo(o2);
//            }
//        });
        Optional<Integer> max_num = list.stream().map(l -> l*l).max((o1, o2) -> o1.compareTo(o2));  // Optional[3249]
        System.out.println(max_num); 

        // min 返回流中的最小值,min的参数可以对流进行处理(升序/降序/...)
        Optional<Integer> min_num = list.stream().min((l1, l2) -> l1.compareTo(l2));  // Optional[-11]
        System.out.println(min_num);

        // forEach 流的迭代
        list.stream().forEach(l -> System.out.println(l));

        System.out.println("***");  // 10 5 -1 32 44 -11 57
        // 集合的迭代
        list.forEach(l -> System.out.println(l));  // 10 5 -1 32 44 -11 57

    }
}
归约
// 归约
    @Test
    public void test2() {
        // T reduce(T identity, BinaryOperator<T> accumulator) 第一个参数是初始值,会附加到最后的结果上,第二个参数是对集合中元素的操作,在这里是相加
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer sum = list.stream().reduce(5, (l1, l2) -> Integer.sum(l1, l2));  // 60
        System.out.println(sum);

        // Optional<T> reduce(BinaryOperator<T> accumulator)
        Optional<Integer> sum2 = list.stream().reduce((l1, l2) -> Integer.sum(l1, l2));  // Optional[55]
        System.out.println(sum2);
    }
收集

在这里插入图片描述
在这里插入图片描述

// 收集
    @Test
    public void test3() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> collect = list.stream().filter(l -> l > 5).collect(Collectors.toList());
        collect.forEach(l -> System.out.println(l));

    }

结果:
6
7
8
9
10

Optional类

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
https://www.bilibili.com/video/BV1Kb411W75N?p=687

其它

还有些新版本的特性,俺是个新手,现在也用不到,等以后再来填坑吧! ()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值