Java8新特性:Stream流与Lambda表达式

【STC8G1K08A串口使用】 STC8G1K08A串口打印“Hello world” 阅读详情

在这里插入图片描述

Stream流

1.Stream简介

Stream是Java8提供的一个新的API,它位于java.util.stream包下。Stream API提供了一种新的方式来对Java集合进行操作,它可以将元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等操作。元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。Stream API 提供了一种高效且易于使用的处理数据的方式。

2.Stream概述

2.1 Stream特性

1.stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
2.stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
3.stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

2.2 Stream特点

1.代码简洁:函数编程写出的代码简洁且意图明确,使用stream接口让你从此告别for循环。
2.多核友好:Java函数式编程使得编写并行程序从未如此简单,你需要的全部就是调用一下方法。
3.Stream不存储数据
4.Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。
5.Stream是惰性求值的(延迟执行)

3.Stream创建

3.1 创建步骤

1.创建 Stream
一个数据源(如: 集合、数组), 获取一个流。
2.中间操作
一个中间操作链,对数据源的数据进行处理。
3.终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果 。

3.2 创建实例
1.通过 java.util.Collection.stream() 方法用集合创建流

List<String> list = new ArrayList<>();
//获取一个顺序流
Stream<String> stream = list.stream();
//获取一个并行流
Stream<String> parallelStream = list.parallelStream();

2.使用java.util.Arrays.stream(T[] array)方法用数组创建流

int[] array = {1, 3, 5, 7, 9};
IntStream stream = Arrays.stream(array);

3.使用Stream的静态方法:of()、iterate()、generate()

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
stream.forEach(System.out::println);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println);
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);

4.Stream流程

1)第一步:把集合转换为流stream
2)第二步:操作stream流
stream流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果
获取一个数据源(source)→ 数据转换→执行操作获取想要的结果。

5.Steam的使用

5.1 遍历/匹配

(foreach/find/match)操作

List<Integer> listNum = Arrays.asList(1, 2, 3, 8, 9, 5, 7);

// 遍历输出符合条件的元素
listNum.stream().filter(x -> x > 7).forEach(System.out::println);
// 符合条件的元素匹配第一个
Optional<Integer> findFirst = listNum.stream().filter(x -> x > 7).findFirst();
// 符合条件的元素匹配任意(适用于并行流)
Optional<Integer> findAny = listNum.parallelStream().filter(x -> x > 7).findAny();
// 是否包含符合特定条件的元素
boolean anyMatch = listNum.stream().anyMatch(x -> x > 7);
System.out.println("匹配第一个值:" + findFirst.get());
System.out.println("匹配任意一个值:" + findAny.get());
System.out.println("是否存在大于6的值:" + anyMatch);

//结果
8
9
匹配第一个值:8
匹配任意一个值:9
是否存在大于6的值:true

5.2 中间操作

流方法含义
filter用于通过设置的条件过滤出元素。
distinct返回一个元素各异(根据流所生成元素的hashCode和equals方法实现)的流。
limit会返回一个不超过给定长度的流。
skip返回一个扔掉了前n个元素的流。
map接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”)。
flatMap使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。
sorted返回排序后的流。

5.2.1 筛选(filter)
按照一定的规则校验流中的元素,将符合条件的元素提取到新的流中的操作。

//案例一:筛选出Integer集合中大于6的元素,并打印出来。
public static void main(String[] args) {
    

List<Integer> list = Arrays.asList(0, 6, 3, 5, 1, 2, 9, 7, 8);
Stream<Integer> stream = list.stream();
stream.filter(x -> x > 6).forEach(System.out::println);

}
//结果
9
7
8

//案例二:筛选出Person集合中年龄大于19员工姓名的元素,并打印出来。
public static void main(String[] args) {

    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, "shanghai"));
    personList.add(new Person(2, "lisi", 19, "beijing"));
    personList.add(new Person(3, "wanger", 20, "guangdong"));
    personList.add(new Person(4, "mazi", 21, "jiangxi"));
    personList.add(new Person(5, "laoer", 22, "zhejiang"));
    
    List<String> filterList = personList.stream().filter(x -> x.getAge() > 19).map(Person::getName)
        .collect(Collectors.toList());
    System.out.print("年龄大于19员工姓名:" + filterList);

}

//结果
年龄大于19员工姓名:[wanger, mazi, laoer]

5.2.2 去重(distinct)
通过流中元素的 hashCode() 和 equals() 去除重复元素

//去除重复元素
public static void main(String[] args) {
    List<Integer> list = Arrays.asList(0, 6, 3, 5, 1, 2, 9, 7, 8);
    Stream<Integer> stream = list.stream();
    stream.filter(x -> x > 6).distinct().forEach(System.out::println);
}

//结果
9
7
8

5.2.3 跳过元素limit(n)
跳过n元素,配合limit(n)可实现分页

//跳过前两个元素
public static void main(String[] args) {
    List<Integer> list = Arrays.asList(0, 6, 3, 5, 1, 2, 9, 7, 8);
    Stream<Integer> stream = list.stream();
    stream.filter(x -> x > 6).skip(2).forEach(System.out::println);
}

//结果
8

5.2.4 获取元素skip(n)
获取n个元素

//获取第几个元素
public static void main(String[] args) {
    List<Integer> list = Arrays.asList(0, 6, 3, 5, 1, 2, 9, 7, 8);
    Stream<Integer> stream = list.stream();
    stream.filter(x -> x > 6).limit(2).forEach(System.out::println);
}

//结果
9
7

5.2.5 映射(map/flatMap)
可以将一个流的元素按照一定的映射规则映射到另一个流中

  • map: 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap: 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

其实map方法就相当于Collaction的add方法,如果add的是个集合得话就会变成二维数组,而flatMap 的话就相当于Collaction的addAll方法,参数如果是集合得话,只是将2个集合合并,而不是变成二维数组。

//案列一:整个数组的数组元素+10
public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 2, 3, 4);
    List<Integer> collect = list.stream().map(x -> x + 10).collect(Collectors.toList());
    System.out.println(collect);
}

//结果
[11, 12, 13, 14]

//案列二:将两个字符数组合并成一个新的字符数组。
public static void main(String[] args) {

    List<String> list = Arrays.asList("a,b,c,d", "e,f,g,h");
    List<String> listNew = list.stream().flatMap(s -> {
        // 将每个元素转换成一个stream
        String[] split = s.split(",");
        Stream<String> s2 = Arrays.stream(split);
        return s2;
    }).collect(Collectors.toList());
    System.out.println("转换前的数据:" + list);
    System.out.println("转换后后的数据:" + listNew);

}

//结果
转换前的数据:[a,b,c,d, e,f,g,h]
    转换后后的数据:[a, b, c, d, e, f, g, h]


    //案列三:将集合里的元素由小写变大写:
    List<String> list = Arrays.asList("a", "b", "c", "d");
List<String> results = list.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(results);

//结果
{A, B, C, D}

//案列四:每个员工工资加3000
public static void main(String[] args) {

    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, 4000, "shanghai"));
    personList.add(new Person(2, "lisi", 19, 5000, "beijing"));
    personList.add(new Person(3, "wanger", 20, 6000, "guangdong"));
    personList.add(new Person(4, "mazi", 21, 7000, "jiangxi"));
    personList.add(new Person(5, "laoer", 22, 8000, "zhejiang"));

    // 不改变原来员工工资集合的方式
    List<Person> personListNew = personList.stream().map(person -> {
        Person personNew = new Person(0, person.getName(), 0, 0, null);
        personNew.setSalary(person.getSalary() + 3000);
        return personNew;
    }).collect(Collectors.toList());
    System.out.println("一次改动前:" +
                       personList.get(0).getName() + "-->" + 	personList.get(0).getSalary());
    System.out.println("一次改动后:" +
                       personListNew.get(0).getName() + "-->" + personListNew.get(0).getSalary());

    // 改变原来员工工资集合的方式
    List<Person> personListNew2 = personList.stream().map(person -> {
        person.setSalary(person.getSalary() + 3000);
        return person;
    }).collect(Collectors.toList());
    System.out.println("二次改动前:" +
                       personList.get(0).getName() + "-->" + personListNew.get(0).getSalary());
    System.out.println("二次改动后:" +
                       personListNew2.get(0).getName() + "-->" + personListNew.get(0).getSalary());

}

@Data
static class Person {
    private int id;
    private String name;
    private int age;
    private int salary;
    private String address;

    public Person(int id, String name, int age, int salary, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.address = address;
    }

}

//结果
一次改动前:zhangsan-->4000
一次改动后:zhangsan-->14000
二次改动前:zhangsan-->14000
二次改动后:zhangsan-->14000

5.2.6 排序(sorted)
sorted,中间操作。有两种排序:

  • sorted():自然排序,流中元素需实现 Comparable 接口

  • sorted(Comparator com):Comparator 排序器自定义排序

public static void main(String[] args) {

    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, 4000, "shanghai"));
    personList.add(new Person(2, "lisi", 19, 5000, "beijing"));
    personList.add(new Person(3, "wanger", 20, 6000, "guangdong"));
    personList.add(new Person(4, "mazi", 21, 7000, "jiangxi"));
    personList.add(new Person(5, "laoer", 22, 8000, "zhejiang"));

    //工资排序顺序
    List<Person> collect1 = personList.stream().sorted(Comparator.comparing(Person::getSalary)).collect(Collectors.toList());
    collect1.forEach(System.out::println);

}

//结果
test12.Person(id=1, name=zhangsan, age=18, salary=4000, address=shanghai)
test12.Person(id=2, name=lisi, age=19, salary=5000, address=beijing)
test12.Person(id=3, name=wanger, age=20, salary=6000, address=guangdong)
test12.Person(id=4, name=mazi, age=21, salary=7000, address=jiangxi)
test12.Person(id=5, name=laoer, age=22, salary=8000, address=zhejiang)

sorted排序参考模板

//返回 对象集合以类属性一升序排序
list.stream().sorted(Comparator.comparing(类::属性一));
//返回 对象集合以类属性一降序排序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed());//先以属性一升序,结果进行属性一降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//以属性一降序
//返回 对象集合以类属性一升序 属性二升序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));

//返回 对象集合以类属性一降序 属性二升序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//先以属性一升序,升序结果进行属性一降序,再进行属性二升序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//先以属性一降序,再进行属性二升序

//返回 对象集合以类属性一降序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序

5.3 终止操作

流方法含义
anyMatch检查是否至少匹配一个元素,返回boolean。
allMatch检查是否匹配所有元素,返回boolean。
noneMatch检查是否没有匹配所有元素,返回boolean。
findAny将返回当前流中的任意元素。
findFirst返回第一个元素。
forEach遍历流。
collect收集器,将流转换为其他形式。
reduce可以将流中元素反复结合起来,得到一个值。
max/min/count返回流中元素最大/最小/总数。

5.3.2 收集(collect)
①归集(toList/toSet/toMap)

转化成新的List
List<> new = old.stream().collect(Collectors.toList());

转化成Map
Map<T,E> new= old.stream().collect(Collectors.toMap(T,E));

转换成set集合
Set<> new =old.stream().Collectors.toSet();

转换成特定的set集合
TreeSet<> new =old.stream().Collectors.toCollection(TreeSet::new);

转化成新的List

原始data:
List<User> userList = new ArrayList<>();
userList.add(new User(1, "张三", 18));
userList.add(new User(2, "李四", 19));
userList.add(new User(3, "王五", 20));

//user的id提取出来
List<User> users = userList;
List<Integer> idList = users.stream().map(User::getId).collect(Collectors.toList());
//{1, 2, 3}
System.out.println(idList);

转化成Map

//1.两个参数的用法
//将userList转化为key为id,value为User对象的map
Map<Integer, User> map1 = userList.stream().collect(Collectors.toMap(User::getId, p -> p));
Map<Integer, User> map2 = userList.stream().collect(Collectors.toMap(User::getId, p -> p));

//结果
{
    1: User(1, "张三", 18)
        2: User(2, "李四", 19)
            3: User(3, "王五", 20)
}

//2.三个参数的用法
Map<Integer, String> map3 = userList.stream().collect(Collectors.toMap(User::getAge, User::getName, (a, b) -> b));

//结果
{
    19: "李四"
        20: "王五"
}

//Collectors.groupingBy()
//当你想获取key是age的map,又不想覆盖掉重复项数据
Map<Integer, List<User>> map4 = userList.stream().collect(Collectors.groupingBy(User::getAge));
System.out.println(map4);

//结果
{
    18: [User(1, "张三", 18), User(3, "王五", 19)]
    19: [User(2, "李四", 20)]
}

②统计(count/averaging)
Collectors提供了一系列用于数据统计的静态方法:

计数:count
平均值:averagingInt、averagingLong、averagingDouble
最值:maxBy、minBy
求和:summingInt、summingLong、summingDouble
统计以上所有:summarizingInt、summarizingLong、summarizingDouble

public static void main(String[] args) {
    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, 4000, "shanghai"));
    personList.add(new Person(2, "lisi", 19, 5000, "beijing"));
    personList.add(new Person(3, "wanger", 20, 6000, "guangdong"));
    personList.add(new Person(4, "mazi", 21, 7000, "jiangxi"));
    personList.add(new Person(5, "laoer", 22, 8000, "zhejiang"));

    // 求总数
    Long count = personList.stream().collect(Collectors.counting());
    // 求平均工资
    Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
    // 求最高工资
    Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
    // 求工资之和
    Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
    // 一次性统计所有信息
    DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

    System.out.println("员工总数:" + count);
    System.out.println("员工平均工资:" + average);
    System.out.println("员工工资总和:" + sum);
    System.out.println("员工工资所有统计:" + collect);

}

//结果
员工总数:5
员工平均工资:6000.0
员工工资总和:30000
员工工资所有统计:DoubleSummaryStatistics{count=5, sum=30000.000000, min=4000.000000, average=6000.000000, max=8000.000000}

③分组(partitioningBy/groupingBy)

  • 分区:将stream按条件分为两个Map,比如员工按薪资是否高于 8000 分为两部分。

  • 分组:将集合分为多个 Map,比如员工按性别分组。有单级分组和多级分组。

public static void main(String[] args) {
    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, 4000, "shanghai", "男"));
    personList.add(new Person(2, "lisi", 19, 5000, "beijing", "女"));
    personList.add(new Person(3, "wanger", 20, 6000, "guangdong", "男"));
    personList.add(new Person(4, "mazi", 21, 7000, "jiangxi", "男"));
    personList.add(new Person(5, "laoer", 22, 8000, "zhejiang", "女"));

    // 将员工按薪资是否高于8000分组
    Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
    // 将员工按性别分组
    Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
    // 将员工先按性别分组,再按地区分组
    Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getAddress)));
    System.out.println("员工按薪资是否大于5000分组情况:" + part);
    System.out.println("员工按性别分组情况:" + group);
    System.out.println("员工按性别、地区:" + group2);

}

④归约(reducing)
Collectors类提供的reducing方法,相比于stream本身的reduce方法,增加了对自定义归约的支持。

public static void main(String[] args) {
    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, 4000, "shanghai", "男"));
    personList.add(new Person(2, "lisi", 19, 5000, "beijing", "女"));
    personList.add(new Person(3, "wanger", 20, 6000, "guangdong", "男"));
    personList.add(new Person(4, "mazi", 21, 7000, "jiangxi", "男"));
    personList.add(new Person(5, "laoer", 22, 8000, "zhejiang", "女"));

    Integer allAge = personList.stream().map(Person::getAge).collect(Collectors.reducing(Integer::sum)).get();
    System.out.println(allAge);

}  

//结果
100

⑤接合(joining)
joining可以将 stream 中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串。

public static void main(String[] args) {
    List<Person> personList = new ArrayList<Person>();
    personList.add(new Person(1, "zhangsan", 18, 4000, "shanghai", "男"));
    personList.add(new Person(2, "lisi", 19, 5000, "beijing", "女"));
    personList.add(new Person(3, "wanger", 20, 6000, "guangdong", "男"));
    personList.add(new Person(4, "mazi", 21, 7000, "jiangxi", "男"));
    personList.add(new Person(5, "laoer", 22, 8000, "zhejiang", "女"));

    String names = personList.stream().map(t -> t.getName()).collect(Collectors.joining(","));
    System.out.println("所有员工的姓名:" + names);
    List<String> list = Arrays.asList("A", "B", "C");
    String string = list.stream().collect(Collectors.joining("&"));
    System.out.println("拼接后的字符串:" + string);

}

//结果
所有员工的姓名:zhangsan,lisi,wanger,mazi,laoer
拼接后的字符串:A&B&C

5.3.3 归约(reduce)
归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

//求和,求积
public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 7, 9);


    Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
    Optional<Integer> sum1 = list.stream().reduce(Integer::sum);
    Integer sum2 = list.stream().reduce(0, Integer::sum);

    Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
    // 最大值方式1
    Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
    // 最大值方式2
    Integer max1 = list.stream().reduce(1, Integer::max);
    System.out.println("求和:" + sum.get() + "," + sum1.get() + "," + sum2);
    System.out.println("求积:" + product.get());
    System.out.println("求和:" + max.get() + "," + max1);

}

//结果
求和:26,26,26
求积:1512
求和:9,9

5.3.4 聚合(max/min/count)
Collectors提供了一系列用于数据统计的静态方法:

计数:count
平均值:averagingInt、averagingLong、averagingDouble
最值:maxBy、minBy
求和:summingInt、summingLong、summingDouble
统计以上所有:summarizingInt、summarizingLong、summarizingDouble

//获取最长元素
public static void main(String[] args) {
    List<String> list = Arrays.asList("asdas", "asdasdasd", "sdasd", "fdfdf", "qqe");
    Optional<String> max = list.stream().max(Comparator.comparing(String::length));
    System.out.println("最长的字符串:" + max.get());
}

//结果
最长的字符串:asdasdasd

5.3.5 匹配(find/match)

//匹配示例
public static void main(String[] args) {
    List<String> strings = Arrays.asList("123", "456", "abc", "sdf", "qwe", "qw2", "qwe");
    //anyMatch  判断集合中是否至少存在一个元素满足条件
    boolean a = strings.stream().anyMatch("123"::equals);
    System.out.println(a);
    //allMatch 判断集合中是否所有元素都满足条件
    boolean b = strings.stream().allMatch("123"::equals);
    System.out.println(b);
    //noneMatch 判断集合中是否所有元素都不满足条件
    boolean c = strings.stream().noneMatch("123"::equals);
    System.out.println(c);
    //findAny 返回当前流中任意元素
    Optional<String> any = strings.stream().findAny();
    any.ifPresent(System.out::println);
    //findFirst 返回当前流中第一个元素
    Optional<String> first = strings.stream().findFirst();
    first.ifPresent(System.out::println);
}

//结果
true
false
false
123
123

6.Steam的总结

Stream极大的简化了开发的代码量,Stream API提供了多个方法对集合进行映射、过滤、排序等操作,其操作不会对原始的集合产生影响。

Lambda表达式

1.Lambda简介

Lambda 表达式是一种轻量级的匿名函数,它允许以更简洁的方式定义函数,通常用于函数式接口(Functional Interfaces)。Lambda 表达式可以明显简化变量代码,提高代码的可读性。

2.Lambda基本语法

Lambda表达式在Java语言中引入了一个操作符 ->,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:

左侧:参数列表,指定了Lambda表达式需要的所有参数。
右侧:表达式主体,制定了Lambda体,即Lambda表达式要执行的功能。
语法:

(parameters) -> expression
或
(parameters) -> { statements; }

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但无参数或多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

3.Lambda不同情况语法

(1)语法格式一:无参,无返回值,Lambda体只需一条语句。如下:

  @Test
  public void test01(){
    Runnable runnable=()-> System.out.println("Runnable 运行");
    runnable.run();//结果:Runnable 运行
  }

(2)语法格式二:Lambda需要一个参数,无返回值。如下:

  @Test
  public void test02(){
    Consumer<String> consumer=(x)-> System.out.println(x);
    consumer.accept("Hello Consumer");//结果:Hello Consumer
  }

(3)语法格式三:Lambda只需要一个参数时,参数的小括号可以省略,如下:

  public void test02(){
    Consumer<String> consumer=x-> System.out.println(x);
    consumer.accept("Hello Consumer");//结果:Hello Consumer
  }

(4)语法格式四:Lambda需要两个参数,并且Lambda体中有多条语句。

  @Test
  public void test04(){
    Comparator<Integer> com=(x, y)->{
      System.out.println("函数式接口");
      return Integer.compare(x,y);
    };
    System.out.println(com.compare(2,4));//结果:-1
  }

(5)语法格式五:有两个以上参数,有返回值,若Lambda体中只有一条语句,return和大括号都可以省略不写

  @Test
  public void test05(){
    Comparator<Integer> com=(x, y)-> Integer.compare(x,y);
    System.out.println(com.compare(4,2));//结果:1
  }

(6)Lambda表达式的参数列表的数据类型可以省略不写,因为JVM可以通过上下文推断出数据类型,即“类型推断”

  @Test
  public void test06(){
    Comparator<Integer> com=(Integer x, Integer y)-> Integer.compare(x,y);
    System.out.println(com.compare(4,2));//结果:1
  }

类型推断:在执行javac编译程序时,JVM根据程序的上下文推断出了参数的类型。Lambda表达式依赖于上下文环境。

语法背诵口诀:左右遇一括号省,左侧推断类型省,能省则省。

4.Lambda的应用

Lambda 表达式在许多 Java 编程场景中都非常有用。以下是一些常见的应用示例:

4.1集合操作

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> doubledNumbers = numbers.stream()
        .map(x -> x * 2)
        .collect(Collectors.toList());

Lambda 表达式可以用于集合操作,例如映射、过滤和排序。

4.2线程和线程

Thread thread = new Thread(() -> {
    System.out.println("Hello from a Lambda thread!");
});

Lambda 表达式可用于简化线程创建和执行。

4.3事件处理

button.addActionListener(e -> {
    System.out.println("Button clicked!");
});

Lambda 表达式可用于简化事件处理。

5.Lambda注意事项

在使用 Lambda 表达式时,有一些注意事项需要考虑:

  • Lambda 表达式通常用于函数式接口,这意味着接口只能有一个抽象方法。
  • 参数的类型可以简洁,编译器会根据上下文进行类型推断。
  • 如果Lambda表达式只有一个参数,甚至可以省略参数的小括号。
  • 表达式主体可以是单行表达式,也可以是代码块。
  • 在代码块中使用多行代码时,需要使用return语句返回结果。

6.Lambda的总结

Lambda表达式是Java 8引入的一项重要特性,它提供了一种简洁、可执行性更高的方式来定义函数。通过不同的匿名方式和注意事项可以更好地理解和应用Lambda表达式,提高代码的可维护性和可执行性。
在这里插入图片描述

Cadence OrCAD Capture 保持元器件编号情况复制元件,复制后元器件编号与复制前不同的问题解决 如下图所示复制时,已经勾选了“Preserve reference on copy”但是复制后的编号却与复制前不一样。本文简单介绍其原因及解决方法。 阅读详情

相关推荐

PowerDesigner16.5下载和安装教程

一、软件下载 1.下载地址(不用复制,直接点击下载链接即可):链接:https://pan.baidu.com/s/1MSnWHWt3SO2Uz5dt9AANAg提取码:z9kk 二、软件安装 1.下载安装包(包含安装文件、汉化包、注册文件) 2.下载后文件内容如下 3....

cicong2374的博客 10万+

万字详解Stream流以及Lambda(看这一篇就够用)

Stream流和Lambda表达式是Java 8中的两个重要特性,它们可以使得代码更加简洁、可读、灵活,同时可以提高代码的效率和可维护性。如果您还没有使用过Stream流和Lambda表达式,那么希望这篇教程能够帮助您入门。

Sunshineづ 3130

服务器报错:“Unhealthy status reported by this UEFI driver without specific error message”.. 记录解决过程

服务器开机报错:Unhealthy status reported by this UEFI driver without specific...

ayychiguoguo的博客 4398

Java 基础 —— Java 8 新特性 stream 与 Lambda

一、Stream 简介 Java 8 引入了全新的 Stream API,这里的 Stream 和 I/O 流不同,它更像具有 Iterable 的集合类,但行为和集合类又有所不同。Stream 是 Java 8 的新特性,是对容器对象功能的增强,它专注于对容器对象进行各种非常便利、高效的聚合操作(aggregate operation)或者大批量数据操作。Stream 是用函数式编程方式在集合类上进行复杂操作的工具,开发者可以更容易地使用 Lambda 表达式,并且更方便地实现对集合的查找、遍历、过滤以及

IT__learning的博客 2172

LCL滤波器参数设计实战:从理论约束到工程选型指南

本文提供了LCL滤波器参数设计的实战指南,从理论约束到工程选型逐步拆解。核心在于平衡总电感量、电感比与电容值,确保谐振频率落在安全区间,以满足并网电流谐波标准并维持系统稳定。文章以10kW并网逆变器为例,给出了具体的参数计算流程与选型步骤,并强调了寄生参数、阻尼设计等工程实现细节。

c6d7e8f9g的博客 922

自动驾驶IDM与MOBIL模型

IDM模型,自动驾驶

不想学好数学的汽车工程师不是一个好的程序员 1万+

Lambda表达式和Stream流

Lambda表达式语法详解,底层实现原理,Lambda和匿名内部类的对比,StreamAPI,Stream常用方法

KANYEA的博客 771

Stata实战:5步搞定PSM倾向得分匹配(附完整代码与常见报错解决)

本文详细介绍了使用Stata进行PSM(倾向得分匹配)的5步实战流程,包括数据预处理、模型构建、匹配算法选择、匹配质量诊断和结果解释。提供完整代码示例和常见报错解决方案,帮助研究者高效完成实证分析,提升匹配成功率。

weixin_29214559的博客 590

Lambda 和 Stream

Lambda 表达式是一个匿名函数,我们可以把 lambda 表达式理解为一段可以传递的代码(将代码段像数据一样传递)。使用它可以写出更简洁, 更灵活的代码。作为一种更紧凑的代码风格,使 java 语言的表达式能力得到的提升。Lambda 表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能。1.3表达式的结构Lambda 表达式可以具有零个,一个或多个参数。可以显式声明参数的类型,也可以由编译器自动从上下文推断参数的类型。

m0_63660547的博客 629

多智能体强化学习MATD3算法完整复现与分析

多智能体强化学习MATD3算法复现与分析摘要 MATD3算法是多智能体深度强化学习领域的重要进展,通过改进MADDPG算法,引入双Q学习、延迟策略更新和目标策略平滑等技术,显著提升了算法稳定性。本文完整复现了MATD3算法,详细解析了其数学原理,包括部分可观测马尔可夫博弈模型和TD3核心思想。在实现层面,设计了集中式Critic和分布式Actor的神经网络架构,采用PyTorch框架构建了Actor-Critic网络模块,包含精心设计的权重初始化和训练流程。该算法有效解决了多智能体环境中的非平稳性、信用分配

max500600的博客 529

2026.2.3:OpenClaw国内安装教程,国内网络使用,服务器部署,对接飞书

本文介绍了如何创建飞书应用并接入OpenClaw机器人的完整流程。主要内容包括:1)在飞书开放平台创建企业自建应用,添加机器人能力并开通相关权限;2)在Windows11系统上安装OpenClaw,完成配置文件的修改(需将bind改为"lan");3)配置MiniMax国内接口地址,重启gateway服务。整个过程涵盖了应用创建、权限设置、软件安装、服务配置等关键步骤,为开发者提供了详细的飞书机器人接入指南。

拥抱具身智能,昇腾Ascend C 3994

java Stream流与Lambda表达式

Stream流:

weixin_45703155的博客 2202

国债期货的日线趋势跟踪策略实现(基于backtrader框架)

通过backtrader框架,我们可以轻松地实现国债期货的日线趋势跟踪策略,并进行回测和验证。通过这种策略,我们可以尝试捕捉国债期货价格的短期趋势,并根据趋势的方向进行交易决策。backtrader提供了许多内置的指标、订单类型和其他功能,可以帮助你进一步优化和改进你的策略。它提供了丰富的工具和功能,使我们能够快速实现和验证我们的交易想法。方法中,我们根据当前价格和前一天的价格判断趋势的方向,并根据趋势的变化进行买入或卖出操作。然后,我们设置了初始资金和交易手续费,并将我们定义的策略。来跟踪每日的收盘价。

NisyPhilosophy的博客 404

Java 8 新特性:Lambda 表达式与 Stream 流,重构你的编码效率(上篇:Lambda 表达式)

Java 8 引入的 Lambda 表达式和 Stream API 彻底革新了数据处理方式。Lambda 简化了函数式接口的使用,使代码更精炼;而 Stream 提供了强大的集合操作能力,支持函数式编程风格。本文将快速带领你掌握这两项特性,展示如何用更少的代码做更多的事情,提升开发效率和代码质量,让编程成为一门艺术。无论你是新手还是资深开发者,都将受益于这一现代 Java 编程之旅。

欢迎来到我的技术空间!我是一名经验丰富的Java开发工程师,热衷于分享我在软件开发领域的知识和心得。在这个博客里,您会发现一系列关于Java编程的文章,包括最佳实践、技术趋势、代码优化技巧以及一些有趣的项目案例。无论是初学者还是有经验的开发者,都能在这里找 1640

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Java 8 新特性:Lambda 表达式与 Stream 流,重构你的编码效率(下篇:stream流)

Java 8 引入的 Lambda 表达式和 Stream API 彻底革新了数据处理方式。Lambda 简化了函数式接口的使用,使代码更精炼;而 Stream 提供了强大的集合操作能力,支持函数式编程风格。本文将快速带领你掌握这两项特性,展示如何用更少的代码做更多的事情,提升开发效率和代码质量,让编程成为一门艺术。无论你是新手还是资深开发者,都将受益于这一现代 Java 编程之旅。

欢迎来到我的技术空间!我是一名经验丰富的Java开发工程师,热衷于分享我在软件开发领域的知识和心得。在这个博客里,您会发现一系列关于Java编程的文章,包括最佳实践、技术趋势、代码优化技巧以及一些有趣的项目案例。无论是初学者还是有经验的开发者,都能在这里找 818

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java 8新特性:Lambda 表达式、函数式接口、Stream流、Optional 类

Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例。Lambda 表达式新的语法元素和操作符。这个操作符为 “->” ,被称 为 Lambda 操作符或剪头操作符。右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。orElse(T t) : 如果调用对象包含值,返回该值,否则返回t。map():映射,可以用lambda表达式获取里面对象的值。可以通过 Lambda 表达式来创建该接口的对象。

qq_43185254的博客 709

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Java 8 新特性全面解析:新增类、方法、接口属性、Lambda表达式、方法引用、函数式接口、Stream流及重复注解机制

Java 8 作为 Java 语言的一个重要版本,引入了许多新特性,如 Lambda 表达式、方法引用、函数式接口、Stream 流等。本文将详细介绍这些新特性,包括新增的类、方法、接口属性,以及它们的使用方法和实际应用场景。同时,本文还将探讨重复注解机制,帮助读者全面了解 Java 8 的新特性。

2301_81724645的博客 1172

Java8新特性lambda和stream系列

目录前言一. Java8新特性之lambda表达式二. Java8新特性之四大函数式接口1. default关键字介绍2. 函数式接口介绍3. 函数型接口 Function 前言 Java8是Java的一个核心版本,添加了许多新的功能和操作,也是Java中使用最高的一个版本即使现在Java16都已经出了。不少人依然对Java8这些特性不了解,甚至看不懂代码。就让本篇文章带你去了解下这些新特性 Lambda 表达式 函数式接口 stream流系列操作 :: 表达式 在写这个文章之前,我对此只是略有了解,甚

杜莱的博客 532

jdk8的新特性stream流-String等

1.内部类. 2.lambda表达式 3.stream流(补充)4.链式编程 5.泛型 6.Optional对象判空

weixin_64035205的博客 234

Java8新特性速览

文章目录一、接口中的默认方法二、Lambda表达式2.1 什么是Lambda2.2 Lambda表达式规范2.3 Lambda表达式基础语法2.4 Lambda表达式用法实例三、Stream流3.1 什么是Stream流3.2 Java8内置四种函数接口3.3 Stream流的基础用法实例3.4 方法引入四、OptionalOptional核心API 一、接口中的默认方法 JDK1.8之前接口中定义的方法都是没有方法体的(抽象方法),都需要实现类去实现: public interface demo {

X_trans的博客 488

JAVA学习线路:day13-JDK8新特性

心得: 我是一名正在自学的java的即将毕业的大学生 总结笔记是为了让自己更好的理解和加深印象。可能不是那么美观,自己可以看懂就好 所有的文档和源代码都开源在GitHub: https://github.com/kun213/JavaNotes上了。希望我们可以一起加油,一起学习,一起交流 day13 JDK8新特性【Lambda、函数式接口、Stream流】 今日学习内容-2020.10.13day13 JDK8新特性【Lambda、函数式接口、Stream流】一、Lambda表达式1.1 理解函数式.

CodeBull_K的博客 722

Jdk1.8的新特性

目录 函数式接口和Lambda表达式 方法引用 Stream流 新时间日期API 一、Lambda表达式 函数式接口中必须唯一有一个未实现的抽象方法,一般函数式接口建议添加注解@FunctionInterface,以下代码展示了jdk1.8的四大函数式接口和自定义接口 /** * 消费型接口, 有参无返回值 */ C...

Peppa_Pig_0325的博客 305

Java8新特性整理笔记

Java8新特性整理笔记 Java8新特性包括:接口内允许添加默认实现的方法、Lambda表达式、函数式接口、Stream流操作等。在我看来,每一个新特性都是一件比较好的工具,但是当他们组合在一起使用的时候就发生质变,就好比一把瑞士军刀。下面我会利用四大核心函数式接口结合其他几种新特性达到优化代码的效果。 如果读者完全没有接触过这些新特性可以先参考我的文章: Java lambda语法和函数式编程...

走不动的木木 469

Java8新特性:新特性预览

Java8新特性:【一】新特性预览 Java【JDK1.8】作为我们最常用到的一个版本,它于2014年3月18日发布,发布公司为Oracle。这个版本就好像一个分水岭,带来的新特性为开发人员提供了巨大的便利。你是否还未使用过这些新特性了? 掌握一下几个新的特性你在开发当中将事半功倍 Lambda 表达式 : Lambda表达式可以将一个函数作为一个方法的参数传递 Lambda使代码变得简介紧凑 方法引用 通过方法的名字去指向这个方法 方法引用使代码紧凑简洁,减少冗余代码。 Stream

qq_40889132的博客 160

一文搞定Lambda表达式,Stream流,方法引用,Optional(JDK8新特性)

Lambda 表达式是一种(没有名字的函数),可以作为方法参数传递,用于简化(Functional Interface)的实现。简单来说,要用Lambda表达式,前提是必有函数式接口。函数式接口:有且仅有一个抽象方法的接口(可用注解标注)(parameters) -> statements 参数 -> 业务代码 或者如下的格式,适用于多行1. 集合操作(配合 Stream API)2. 线程任务3. 事件监听(GUI / 回调)4. 自定义函数式接口代码简洁,可读性强,支持函数式编程。

老肖的博客 941

Jdk1.8新特性

Jdk1.8新特性 一、在接口中提供默认的方法实现 public interface Test { double calculate(int a); default double sqrt(int a) { return Math.sqrt(a); } } 二、Lambda 表达式 1、Collections.sort (),入参是一个 List 集合,和一个 Comparator 比较器,可以对给定的 List 集合进行排序。 Collections.sort(names, (String a, Stri

chuang_pin的博客 327
上一篇: Java实现远程文件复制(基于SCP命令)
下一篇: Nginx详解:反向代理、负载均衡和高性能Web服务器
霁晨晨晨
博客等级 码龄4年 359粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

霁晨晨晨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值