java新特性

Lambda表达式

什么是Lambda表达式?

可以将Lambda表达式理解为一个匿名函数;允许将函数像变量那样作为实参传递给另一个函数; 这就是函数式编程,函数是一等公民。

为什么要引入Lambda表达式?

Lambda表达式能够让程序员的编程更加高效

举例分析有多高效:

public class TestLambda {
       public static void main(String[] args) {
       Thread thread = new Thread(new MyRunnable());
       thread.start();
       thread.close();
    }
}
class MyRunnable implements Runnable{
	    @Override
        public void run() {
            System.out.println("Hello");
        }
}

为了使这段代码变得更加简洁,可以使用匿名内部类重构一下

package com.isea.java;
public class TestLambda {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello");
            }
        }).start();
    }
}

上面的代码可以换成这样的,我们将new 的接口,赋值给线程的引用:

public class TestLambda {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello");
            }
        });
        thread.start();
    }
}

而上面的这段代码,不是最简单的,还可以进一步简化

public class TestLambda {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("Hello")).start();
    }
}

这就是lambda的魅力!

lambda表达式六大语法

在这里插入图片描述
在这里插入图片描述
类型推断
有没有发现,上述 Lambda 表达式中,我们没有手动指定参数类型,参数类型都是由编译器推断得出的。
为什么可以这样写呢?这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。这就是所谓的“类型推断”。

Lamda 表达式不能修改局部变量值

我们可以直接在 lambda 表达式中访问外部的局部变量:

final int num = 1;// num 必须不可被后面的代码修改,所以这里的num用final修饰了,不加final也行(jvm会自动帮我加上)
Converter<Integer, String> stringConverter =
        (from) -> String.valueOf(from + num);

stringConverter.convert(2);     // 3

下面的就无法编译:

int num = 1;
Converter<Integer, String> stringConverter =
        (from) -> String.valueOf(from + num++);//不允许修改num,编译不通过

Stream API

Stream被翻译为流,它的工作过程像将一瓶水导入有很多过滤阀的管道一样,水每经过一个过滤阀,便被操作一次,比如过滤,转换等,最后管道的另外一头有一个容器负责接收剩下的水。
示意图如下:
在这里插入图片描述
首先通过source产生流,然后依次通过一些中间操作,比如过滤,转换,限制等,最后结束对流的操作。

Stream也可以理解为一个更加高级的迭代器,主要的作用便是遍历其中每一个元素。

Stream的好处:
Stream作为Java 8的一大亮点,它专门针对集合的各种操作提供各种非常便利,简单,高效的API
Stream API主要是通过Lambda表达式完成,极大的提高了程序的效率和可读性,同时Stram API中自带的并行流使得并发处理集合的门槛再次降低,使用Stream API编程无需多写一行多线程的大门就可以非常方便的写出高性能的并发程序。使用Stream API能够使你的代码更加优雅。

Stream的特点

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream 操作三个步骤

1、 创建 Stream
一个数据源(如:集合、数组),获取一个流

2、 中间操作
一个中间操作链,对数据源的数据进行处理

3、终止操作(终端操作)
一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
在这里插入图片描述

Stream的创建方式

创建 Stream方式一:通过集合

Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:

接口
Stream<E> stream() : 返回一个顺序流
Stream<E> parallelStream() : 返回一个并行流

举例:employees是一个list
//        default Stream<E> stream() : 返回一个顺序流
        Stream<Employee> stream = employees.stream();

//        default Stream<E> parallelStream() : 返回一个并行流
        Stream<Employee> parallelStream = employees.parallelStream();

创建 Stream方式二:通过数组

static <T> Stream<T> stream(T[] array): 返回一个流

 IntStream stream = Arrays.stream(arr); //arr是一个数组

创建 Stream方式三:通过Stream的of()

可以调用Stream类的静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数。

public static<T> Stream<T> of(T... values) : 返回一个流

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

创建 Stream方式四:创建无限流

可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流

1、迭代
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) 
2、生成
public static<T> Stream<T> generate(Supplier<T> s) 

//      迭代
//      public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
        //遍历前10个偶数
        Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);


//      生成
//      public static<T> Stream<T> generate(Supplier<T> s)
        Stream.generate(Math::random).limit(10).forEach(System.out::println);

Stream 的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

筛选和切片

在这里插入图片描述
举例

stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println); //排除工资低于7000的
list.stream().limit(3).forEach(System.out::println); 

映射

在这里插入图片描述

List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.stream().map(str -> str.toUpperCase()).forEach(System.out::print);//AABBCCDD

排序

在这里插入图片描述

// sorted()——自然排序
List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);
list.stream().sorted().forEach(System.out::println); 

list对象所属的类如果没有实现Comparable接口的话,就会无法排序而报错。

Stream 的终止操作

 终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:Integer、String、List、Map,甚至是 void 。
 流进行了终止操作后,不能再次使用。

collect 收集汇总

collect(Collector c)
接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、 Map)。

另外, Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:
在这里插入图片描述
在这里插入图片描述
练习1

查找工资大于6000的员工,结果返回为一个ListSet
List<Employee> employeeList = employees.stream()
                              .filter(e -> e.getSalary() > 6000)
                              .collect(Collectors.toList());

练习2

List<String> list = Arrays.asList("aa", "bb", "cc", "dd");

Map<String, List<String>> collect = list.stream().collect(
        Collectors.groupingBy(
                str -> str
        ));
for (String s : collect.keySet()) {
    System.out.println(s+" "+collect.get(s));
}
//        dd [dd]
//        cc [cc]
//        bb [bb]
//        aa [aa]

重点

在这里插入图片描述

规约

在这里插入图片描述

List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, Integer::sum); //55

匹配与查找

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值