Java详细分析Lambda表达式与Stream流的使用方法

目录
  • Lambda
  • Stream流

Lambda

Lambda 表达式是一个匿名函数,我们可以把 lambda 表达式理解为一段可以传递的代码(将代码段像数据一样传递)。使用它可以写出更简洁, 更灵活的代码。作为一种更紧凑的代码风格,使 java 语言的表达式能力得到的提升。

我们可以知道, Lambda表达式是为简化语法而存在的

ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.sort(new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o2.compareTo(o1);
    }
});
System.out.println(list);

这里有一个List集合 , 并添加了一些元素, 我们想对他进行排序, 并且按照降序的方式来排 , 在没接触Lambda表达式之前 ,我们是向上面那样去做的

上面这种方式是匿名内部类写法 , 调用sort()方法时, 要求传入一个比较器, Comparator是一个接口, 接口可以new吗? 肯定是不能的 , 所以这里是有一个隐藏的类去实现了Comparator接口, 并且重写了它里面的compare()方法 , 来制定我们的比较规则, 这个隐藏的类没有类名, 就是我们这里所说的匿名内部类 , 但方法也是不能作为参数去传递的, 所以我们new了这个匿名内部类的对象 , 包裹了实现后的方法

但是现在我们嫌这个写法太啰嗦了 ,我们使用Lambda来看看

// Lambda表达式
list.sort((o1,o2) -> {return o2.compareTo(o1);});

这就和上面的匿名内部类写法是一样的

Lambda表达式的结构 :

左侧:lambda 表达式的参数列表

右侧:lambda 表达式中需要执行的功能,即 lambda 体

(arg1, arg2...) -> { body }

(type1 arg1, type2 arg2...) -> { body }

常见例子

无参数,无返回值,lambda 体中只有一行代码时,{}可以忽略 () -> System.out.println("Hello World");

无参数,有返回值  () -> { return 3.1415 };

有参数,无返回值  (String s) -> { System.out.println(s); }

有一个参数,无返回值 s -> { System.out.println(s); }

有多个参数,有返回值 (int a, int b) -> { return a + b; }

有多个参数,表达式参数类型可以不写,jvm 可以根据上下文进行类型推断 (a, b) -> { return a - b; }

功能接口

功能接口上面一般会有这样一个注解标签@FunctionalInterface , 它表示此接口只有一个抽象方法, 当你注释的接口违反了 Functional Interface 的契约时,它可以用于编译器级错误

例如 : 我们刚使用的comparator接口就有这样的注解

Stream流

允许你以声明式的方式处理数据集合,可以把 它看作是遍历数据集的高级迭代器。此外与 stream 与 lambada 表达示结合后 编码效率与大大提高,并且可读性更强。

流更偏向于数据处理和计算,比如 filter、map、find、sort 等。简单来说,我们通过一个集合的 stream 方法获取一个流,然后对流进行一 系列流操作,最后再构建成我们需要的数据集合。

我们常常将Stream流与Lambda表达式结合来编码 , 那么如何来使用呢 ?

这里分为 3 步 :

1. 获得流

2. 中间操作

3. 终端操作

中间操作(往往对数据进行筛选)

  • filter:过滤流中的某些元素,
  • sorted(): 自然排序,流中元素需实现 Comparable 接口
  • distinct: 去除重复元素
  • limit(n): 获取 n 个元素
  • skip(n): 跳过 n 元素,配合 limit(n)可实现分页
  • map(): 将其映射成一个新的元素

终端操作(往往对结果集进行处理)

  • forEach: 遍历流中的元素
  • toArray:将流中的元素倒入一个数组
  • Min:返回流中元素最小值   Max:返回流中元素最大值
  • count:返回流中元素的总个数
  • Reduce:所有元素求和
  • anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足条件则返回 true,否则返回
  • falseallMatch:接收一个 Predicate 函数,当流中每个元素都符合条件时才返回 true,否则返回 false
  • findFirst:返回流中第一个元素
  • collect:将流中的元素倒入一个集合,Collection 或 Map
Integer[] arr = new Integer[]{1,4,3,2,5,5};
Arrays.stream(arr)    //拿到流
    .filter((a) -> {return a>3;})  //中间操作,过滤
    .forEach((a) -> {   //终端操作,遍历
        System.out.println(a);
    });
Integer[] arr = new Integer[]{1,4,3,2,5,5};
Object[] objects = Arrays.stream(arr)
    .sorted().distinct() //排序并去重
    .toArray();  //转数组
System.out.println(Arrays.toString(objects));
Integer[] arr = new Integer[]{1,4,3,2,5,5};
Integer max = Arrays.stream(arr).distinct()
    .max(((o1, o2) -> {    //去重返回最大值
        return o1 - o2;
    })).get();  //拿到这个值
//此处max为终端操作,返回的已经不是流,而是一个OPtion的对象
//它里面有一个get()方法可以返回这个值
System.out.println(max);
Integer[] arr = new Integer[]{1,4,3,2,5,5};
long count = Arrays.stream(arr).distinct()
    .count();   //返回总个数
System.out.println(count);
Integer[] arr = new Integer[]{1,4,3,2,5,5};
Integer i = Arrays.stream(arr).distinct()
    .reduce((o1, o2) -> {  //所有元素求和
        return o1 + o2;
    })
    .get();
System.out.println(i);

这里需要注意的是中间操作的map()方法和终端操作的collect()方法

设计一个Apple类

public class Apple {
    private Integer num;
    private String name;
    private String color;
}

并给出 构造 , set 和 get 方法 ,此处由于篇幅 原因省略

List<Apple> list = new ArrayList<>();
list.add(new Apple(100,"苹果1","红色"));
list.add(new Apple(105,"苹果5","红色"));
list.add(new Apple(104,"苹果4","红色"));
list.add(new Apple(103,"苹果3","红色"));
list.add(new Apple(102,"苹果2","红色"));

往一个list添加5个元素

List<String> collect = list.stream()
    //将属性的一列通过get方法映射成流
    .map(Apple::getName)
    //转为一个list集合
    .collect(Collectors.toList());
System.out.println(collect);
List<Apple> collect = list.stream().sorted(((o1, o2) -> {
    //通过num属性自定义排序
    return o1.getNum() - o2.getNum();
    }))
    //转为一个list集合
    .collect(Collectors.toList());
System.out.println(collect);
Map<Integer, String> map = list.stream().sorted(((o1, o2) -> {
    return o1.getNum() - o2.getNum();
    }))
    //转map, 第一个参数为键,第二个参数为值
    .collect(Collectors.toMap(Apple::getNum, Apple::getName));
System.out.println(map);

到此关于Lambda表达式与Stream流就介绍完了,感谢阅读

到此这篇关于Java详细分析Lambda表达式与Stream流的使用方法的文章就介绍到这了,更多相关Java Lambda与Stream内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java8中Lambda表达式使用和Stream API详解

    前言 Java8 的新特性:Lambda表达式.强大的 Stream API.全新时间日期 API.ConcurrentHashMap.MetaSpace.总得来说,Java8 的新特性使 Java 的运行速度更快.代码更少.便于并行.最大化减少空指针异常. 0x00. 前置数据 private List<People> peoples = null; @BeforeEach void before () { peoples = new ArrayList<>(); peoples

  • 吊打Java面试官之Lambda表达式 Stream API

    目录 一.jdk8新特性简介 二.Lambda表达式 简单理解一下Lambda表达式 Lambda表达式的使用 三.函数式接口 1.什么是函数式接口 2.如何理解函数式接口 3.Java内置四大核心函数式接口 四.方法引用与构造器引用 方法引用 构造器引用和数组引用 五.Stream API 1.Stream API的说明 2.为什么要使用Stream API 3.创建Stream的四种方式 4.Stream的中间操作及其测试 5.Stream的终止操作及其测试 六.Optional类的使用 O

  • Java详细分析Lambda表达式与Stream流的使用方法

    目录 Lambda Stream流 Lambda Lambda 表达式是一个匿名函数,我们可以把 lambda 表达式理解为一段可以传递的代码(将代码段像数据一样传递).使用它可以写出更简洁, 更灵活的代码.作为一种更紧凑的代码风格,使 java 语言的表达式能力得到的提升. 我们可以知道, Lambda表达式是为简化语法而存在的 ArrayList<String> list = new ArrayList<>(); list.add("a"); list.ad

  • C++详细分析lambda表达式的本质

    例: stable_sort(words.begin(), words.end(), [](const string& s1, const string& s2) { return s1.size() < s2.size(); }); class ShorterString { public: bool operator()(const string& s1,const string& s2)const { return s1.size() < s2.size(

  • Java分析Lambda表达式Stream流合并分组内对象数据合并

    目录 前言 需求 代码实现 依赖引入 设计实体类 测试代码 前言 之前写过<Lambda使用——JDK8新特性>,现在有一个分组合并的需求正好拿来小试牛刀. 需求 数据出自许多接口数据,需要将几个接口数据根据省份id进行分组合并.举例说明: A接口返回List里面有值的的字段为:provinceId.field1.field2.field3 B接口返回List里面有值的的字段为:provinceId.field4.field5.field6 C接口返回List里面有值的的字段为:provinc

  • 快速入门Java中的Lambda表达式

    Lambda简介 Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块). Lambda表达式还增强了集合库. Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及 java.util.stream 包. 流(stream)就如同迭代器(iterator),但附加了许多

  • 详解Java中的Lambda表达式

    简介 Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块). Lambda表达式还增强了集合库. Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包. 流(stream)就如同迭代器(iterator),但附加了许多额外的功能.

  • Java 进阶使用 Lambda 表达式实现超强的排序功能

    目录 基于Comparator排序 使用 Lambda 表达式替换Comparator匿名内部类 通过静态方法抽取公共的 Lambda 表达式 借助Comparator的comparing方法 多条件排序 在Stream中进行排序 倒序排列 调转排序判断 在Comparator.comparing中定义排序反转 在Stream中定义排序反转 null 值的判断 元素是 null 的笨拙实现 排序条件的字段是 null 文末总结 我们在系统开发过程中,对数据排序是很常见的场景.一般来说,我们可以采

  • C++精要分析lambda表达式的使用

    目录 引言 语法与示例 捕获列表 捕获引用 特殊用法 实现原理 应用 引言 C++要走向现代语言,如果不支持lambda表达式,你很难认为这门语言和现代有什么关系.幸好,从C++11标准起,它就实现了对lambda表达式的支持. 那么,什么是lambda表达式呢? lambda表达式是匿名函数,就是说不用定义函数名,函数实现可以直接嵌入在业务逻辑代码中.诸如python.java.C#等语言,都将其作为基础特性. 其优点是提高了代码的可读性,对于一些无需重用的方法特别适合.例如在容器的迭代中实现

  • Java学习之Lambda表达式的使用详解

    目录 Lamda表达式 函数式接口 Lambda表达式的推导 函数式接口的不同类型 Lambda表达式与函数式接口的简单应用 Lambda表达式的优缺点 Lamda表达式 λ希腊字母表中排序第11位的字母,英文名称为Lambda,它Lambda表达式是Java SE 8中一个重要的新特性,允许通过表达式来代替功能接口,它与其他方法相同,提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块),实际上是属于函数式编程的概念: 语法如下: (参数) ->表达式 或

  • Java中使用Lambda表达式和函数编程示例

    目录 1.简单介绍 2.Lambdas和Scopes 3.Lambdas与局部变量 4.Lambda体与局部变量 5.Lambdas和'This'和'Super'关键字 6.Lambdas和Exceptions 7.预定义的功能接口 1.简单介绍 第一个示例演示变量声明上下文中的lambda.它将lambda()->{System.out.println("running"):}分配给可运行接口类型的变量r. 第二个示例类似,但演示了赋值上下文中的lambda(到先前声明的变量r

  • 关于Java 中的 Lambda 表达式

    这篇文章我们将讨论关于Java 中的 Lambda 表达式,Lambda 表达式是 Java 涉足函数式编程的过程.它接受参数并将其应用于表达式或代码块.以下是语法的基本示例: (parameter1, parameter2) => expression 或者 (parameter1, parameter2) => {code block} Lambda 表达式非常有限,如果它不是 void,则必须立即返回一个值.他们不能使用诸如 if 或 for 之类的关键字来保持简单性.如果需要更多行代码

随机推荐