当前位置: 代码迷 >> 综合 >> java学习(Lambda 表达式、Stream流、FlatMap)
  详细解决方案

java学习(Lambda 表达式、Stream流、FlatMap)

热度:3   发布时间:2024-02-28 02:48:32.0

Lambda 表达式

一个 Lambda 表达式具有下面这样的语法特征。它由三个部分组成:第一部分为一个括号内用逗号分隔的参数列表,参数即函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块。语法如下:

parameter -> expression body

几个最重要的特征:

  • 可选的类型声明:你不用去声明参数的类型。编译器可以从参数的值来推断它是什么类型。
  • 可选的参数周围的括号:你可以不用在括号内声明单个参数。但是对于很多参数的情况,括号是必需的。
  • 可选的大括号:如果表达式体里面只有一个语句,那么你不必用大括号括起来。
  • 可选的返回关键字:如果表达式体只有单个表达式用于值的返回,那么编译器会自动完成这一步。若要指示表达式来返回某个值,则需要使用大括号。
    表达式简单的例子:
// 1. 不需要参数,返回值为 5 
() -> 5  // 2. 接收一个参数(数字类型),返回其2倍的值 
x -> 2 * x  // 3. 接受2个参数(数字),并返回他们的差值 
(x, y) -> x – y  // 4. 接收2个int型整数,返回他们的和 
(int x, int y) -> x + y  // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) 
(String s) -> System.out.print(s)

注意的是:

  • Lambda 表达式优先用于定义功能接口在行内的实现,即单个方法只有一个接口。
  • Lambda 表达式让匿名类不再需要,这为 Java 增添了简洁但实用的函数式编程能力。

方法引用

方法引用可以通过方法的名字来引用其本身。方法引用是通过 :: 符号(双冒号)来描述的。

它可以用来引用下列类型的方法:

  • 构造器引用。语法是 Class::new,或者更一般的 Class::new,要求构造器方法是没有参数;
  • 静态方法引用。语法是Class::static_method。
  • 特定类的任意对象方法引用。它的语法是 Class::method。
  • 特定对象的方法引用,它的语法是 instance::method。

函数式接口

函数式接口是只包含一个方法的接口。例如,带有单个 compareTo 方法的比较接口,被用于比较的场合。
一个使用这些函数式编程的接口的例子:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;public class FunctionTest {
    
//Predicate 是 Java 提供的一个函数式接口,他接受一个参数 t,并执行断言操作返回一个 boolean。public static void eval(List<Integer> list,Predicate<Integer> predicate){
    for(Integer n:list){
    if(predicate.test(n)){
    System.out.println(n);}}}public static void main(String[] args) {
    List<Integer> list=Arrays.asList(0,1,2,3,4,5,6,7,8,9); System.out.println("所有数字是(用foreach遍历):");list.forEach(System.out::println);System.out.println("所有数字是(用方法遍历):");eval(list,n->true);System.out.println("偶数为:");eval(list,n->n%2==0);System.out.println("比5大的数为:");eval(list,n->n>5);}
}

结果为:

所有数字是(用foreach遍历):
0
1
2
3
4
5
6
7
8
9
所有数字是(用方法遍历):
0
1
2
3
4
5
6
7
8
9
偶数为:
0
2
4
6
85大的数为:
6
7
8
9

Stream流

Stream 代表了来自某个源的对象的序列,这些序列支持聚集操作。
Stream 的一些特性:

  • 元素序列:Stream 以序列的形式提供了特定类型的元素的集合。根据需求,它可以获得和计算元素,但不会储存任何元素。
  • 源:Stream 可以将集合、数组和 I/O 资源作为输入源。
  • 聚集操作:Stream 支持诸如 filter、map、limit、reduce 等的聚集操作。
  • 流水技术:许多 Stream 操作返回了流本身,故它们的返回值可以以流水的行式存在。这些操作称之为中间操作,并且它们的功能就是负责输入、处理和向目标输出。collect() 方法是一个终结操作,通常存在于流水线操作的末端,来标记流的结束。
  • 自动迭代:Stream 的操作可以基于已提供的源元素进行内部的迭代,而集合则需要显式的迭代。

相关方法

  • stream():该方法返回一个将集合视为源的连续流。
  • parallelStream():该方法返回一个将集合视为源的并行流。
  • forEach:该方法用于对 Stream 中的每个元素进行迭代操作。下面的代码段演示了如何使用 forEach 方法输出 10 个随机数。
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
  • map:该方法用于将每个元素映射到对应的结果上。下面的代码段演示了怎样用 map 方法输出唯一的某个数的平方。
List<Integer> numbers = Arrays.asList(2, 3, 3, 2, 5, 2, 7);
//get list of unique squares
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
  • filter:该方法用于过滤满足条件的元素。下面的代码段演示了怎样输出使用了过滤方法的空字符串数量。
List<String>strings = Arrays.asList("efg", "", "abc", "bc", "ghij","", "lmn");
//get count of empty string
long count = strings.stream().filter(string -> string.isEmpty()).count();
  • limit:该方法用于减少 Stream 的大小。下面的代码段演示了怎样有限制地输出 10 个随机数。
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
  • sorted:该方法用于对 Stream 排序。下面的代码段演示了怎样以有序的形式输出 10 个随机数。
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
  • 并行处理 ParallelStream 是 Stream 用于并行处理的一种替代方案。下面的代码段演示了如何使用它来输出空字符串的数量。
List<String> strings = Arrays.asList("efg", "", "abc", "bc", "ghij","", "lmn");// 获得空字符串的计数
long count = strings.parallelStream().filter(String::isEmpty).count();
  • Collector 用于合并 Stream 的元素处理结果。它可以用于返回一个字符串列表。
 List<String> strings=Arrays.asList("efg", "", "abc", "bc", "ghij","", "lmn");List<String> filtered=strings.stream().filter(string->!string.isEmpty()).collect(Collectors.toList());System.out.println("Filetered List: "+filtered);String mer=strings.stream().filter(string->!string.isEmpty()).collect(Collectors.joining(", "));System.out.println("merged string: "+mer);

结果

Filetered List: [efg, abc, bc, ghij, lmn]
merged string: efg, abc, bc, ghij, lmn

注:一般filter是对于字符串进行对应,map是对于数字进行对应。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;import javax.swing.JPopupMenu.Separator;public class StreamTest {
    public static void main(String[] args) {
    List<String> strings=Arrays.asList("efg", "", "abc", "bc", "ghij","", "lmn");System.out.println("List: "+strings);
// System.out.println(strings.toString());long count=getCountEmptyStringUsingJava7(strings);System.out.println("Empty Strings: "+count);// count=getCount(strings);count=strings.stream().filter(string->string.length()==3).count();System.out.println("字符串长度为3 的个数:"+count);List<String> filtered=deleteEmpty(strings);System.out.println("消除空字符串后字符串:"+filtered);String merged=getMerged(strings,",");}private static String getMerged(List<String> strings,String separator) {
    // TODO Auto-generated method stubStringBuilder stringbuilder=new StringBuilder();for(String string:strings){
    if(!string.isEmpty()){
    stringbuilder.append(string);stringbuilder.append(separator);}}String mergeString=stringbuilder.toString();return mergeString.substring(0, mergeString.length()-2);}private static List<String> deleteEmpty(List<String> strings) {
    // TODO Auto-generated method stubList<String> filtered=new ArrayList<String>();for(String string:strings){
    if(!string.isEmpty()){
    filtered.add(string);}}return filtered;}private static int getCount(List<String> strings) {
    // TODO Auto-generated method stubint count=0;for(String string:strings){
    if(string.length()==3){
    count++;}}return count;}private static int getCountEmptyStringUsingJava7(List<String> strings) {
    // TODO Auto-generated method stubint count=0;for(String string:strings){
    if(string.isEmpty()){
    count++;}}return count;}
}

FlatMap

FlatMap 用于将多个流合并为一个流,使用 FlatMap 时,表达式的返回值必须是 Stream 类型。而 Map 用于将一种流转化为另外一个流。

public class FlatMapTest {
    public static void main(String[] args) {
    Stream<String> stringStream1=Stream.of("shi yan","shi yan lou","lou yan shi");Stream<String> stringStream2=Stream.of("shi yan","shi yan lou","lou yan shi");Stream<String[]> mapStream=stringStream1.map(v->v.split(" "));Stream<String> flatMapStream=stringStream2.flatMap(v->Arrays.stream(v.split(" ")));System.out.println("mapStream打印:");mapStream.peek(System.out::println).count();System.out.println("flatMapStream打印: ");flatMapStream.peek(System.out::println).count();}
}

结果

mapStream打印:
[Ljava.lang.String;@4eec7777
[Ljava.lang.String;@3b07d329
[Ljava.lang.String;@41629346
flatMapStream打印: 
shi
yan
shi
yan
lou
lou
yan
shi

map将一种类型的流 转换为另外一个类型的流 这里转换成了String[]流。
Arrays.stream将数组转换成了流 这里将分割后的String[],转换成了Stream,但是我们前面定义了三个字符串,所以这里将产生三个Stream,flatMap用于将三个流合并成一个流

  相关解决方案