Java基础——Lambda

注意:其中资料来源于蓝桥云课(https://www.lanqiao.cn/),有兴趣的小伙伴可以去官网学习,这里是小编自己学习后整理的资料,有误之处欢迎留言讨论,谢谢!

函数式编程(函数程序设计 / 泛函编程)

​ 是一种编程典范,它将计算机运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是 λ 演算(lambda calculus)。而且 λ 演算的函数可以接受函数当作输入(引数)和输出(传出值)。

组成

  • 一个括号内用逗号分隔的参数列表,参数即函数式接口里面方法的参数;
  • 一个箭头符号:->
  • 方法体,可以是表达式和代码块
parameter -> expression body

特征

  • 可选的类型声明:你不用去声明参数的类型。编译器可以从参数的值来推断它是什么类型。
  • 可选的参数周围的括号:你可以不用在括号内声明单个参数。但是对于很多参数的情况,括号是必需的。
  • 可选的大括号:如果表达式体里面只有一个语句,那么你不必用大括号括起来。
  • 可选的返回关键字:如果表达式体只有单个表达式用于值的返回,那么编译器会自动完成这一步。若要指示表达式来返回某个值,则需要使用大括号。
import java.net.InterfaceAddress;

/**
 * @author : yingH
 * @create : 2021-12061:32
 * @details :Lambda
 */
public class LambdaTest {
    public static void main(String[] args) {
        LambdaTest t = new LambdaTest();

        // 带有类型声明的表达式
        MathOperation add=(int a,int b)-> a+b;
        // 没有类型声明的表达式
        MathOperation sub=(a,b)->a-b;
        // 带有大括号、带有返回语句的表达式
        MathOperation mul=(int a,int b)->{return a*b;};
        // 没有大括号和return语句的表达式
        MathOperation div=(int a,int b)->a/b;

        System.out.println("10+5=" + t.operation(10, 5, add));
        System.out.println("10-5=" + t.operation(10, 5, sub));
        System.out.println("10*5=" + t.operation(10, 5, mul));
        System.out.println("10/5=" + t.operation(10, 5, div));

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

        // 没有括号的表达式
        GreetingService g1=Message ->  System.out.println("hello "+Message);
        // 有括号的表达式
        GreetingService g2=(Message) -> System.out.println("hello "+Message);

        // 调用sayMessage方法输出结果
        g1.sayMessage("yingH");
        g2.sayMessage("shiyanlou");

    }

    //定义接口和方法
    interface MathOperation{
        int operation(int a,int b);
    }

    interface GreetingService{
        void sayMessage(String Message);
    }

    private int operation(int a,int b,MathOperation mathOperation){
        return mathOperation.operation(a,b);
    }

}

==>
10+5=15
10-5=5
10*5=50
10/5=2
----------------------------------
hello yingH
hello shiyanlou

注意

  • Lambda 表达式优先用于定义功能接口在行内的实现,即单个方法只有一个接口。在上面的例子中,我们用了多个类型的 Lambda 表达式来定义 MathOperation 接口的操作方法。然后我们定义了 GreetingService 的 sayMessage 的实现。
  • Lambda 表达式让匿名类不再需要,这为 Java 增添了简洁但实用的函数式编程能力

作用域

public class LambdaTest {
        final static String salutation = "Hello "; //正确,不可再次赋值
        //static String salutation = "Hello "; //正确,可再次赋值
        //String salutation = "Hello "; //报错
        //final String salutation = "Hello "; //报错

    public static void main(String args[]){
        //final String salutation = "Hello "; //正确,不可再次赋值
        //String salutation = "Hello "; //正确,隐性为 final , 不可再次赋值

        // salution = "welcome to "
        GreetingService greetService1 = message ->
        System.out.println(salutation + message);
        greetService1.sayMessage("Shiyanlou");
    }

    interface GreetingService {
       void sayMessage(String message);
    }
}
==>
Hello Shiyanlou
  • 可访问 static 修饰的成员变量,如果是 final static 修饰,不可再次赋值,只有 static 修饰可再次赋值;
  • 可访问表达式外层的 final 局部变量(不用声明为 final,隐性具有 final 语义),不可再次赋值。

方法引用

​ 通过 :: 符号(双冒号)来描述的。

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

/**
 * @author : yingH
 * @create : 2021-12061:59
 * @details :方法引用
 */
public class LambdaTest3 {
    public static void main(String[] args) {
        ArrayList<Object> names = new ArrayList<>();
        names.add("yingH");
        names.add("Peter");
        names.add("Jack");
        names.add("Rose");
        //     通过System.out::println引用了输出的方法
        names.forEach(System.out::println);
    }
}
===>
yingH
Peter
Jack
Rose

函数式接口

​ 只包含一个方法的接口。

方法

image-20211206020241305

image-20211206020302901

官方API:java.lang.Annotation Type FunctionalInterface

import sun.font.EAttribute;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * @author : yingH
 * @create : 2021-12062:08
 * @details :
 */
public class FunctionTest {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
        System.out.println("All of the numbers");
        eval(list,n->true);
        System.out.println("----------------------------------");
        System.out.println("Even numbers");
        eval(list,n->n%2==0);
        System.out.println("----------------------------------");
        System.out.println("Numbers that greater than  5:");
        eval(list,n->n>5);
    }

    public static void eval(List<Integer>list, Predicate<Integer>predicate){
        for (Integer n:list){
            if (predicate.test(n)){
                System.out.println(n);
            }
        }
    }

}

==>
All of the numbers
0
1
2
3
4
5
6
7
8
9
----------------------------------
Even numbers
0
2
4
6
8
----------------------------------
Numbers that greater than  5:
6
7
8
9

Predicate

​ Predicate 是 Java 提供的一个函数式接口,他接受一个参数 t,并执行断言操作返回一个 boolean

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}
import java.util.function.IntPredicate;
import java.util.function.Predicate;
import java.util.stream.IntStream;

/**
 * @author : yingH
 * @create : 2021-12062:15
 * @details :
 */
public class PredicateDemo {
    public static void main(String[] args) {
        //简单使用  判断a是否大于50
        Predicate<Integer> predicate=a->a>50;
        System.out.println(predicate.test(52));
        System.out.println("------------------------------");

        //如果只断言int类型,可以直接使用 IntPredicate
        IntPredicate intPredicate=a->a>50;

        // System.out.println(intPredicate.test(50));
        IntStream.of(10,11,44,59,46,55,99,88,50)
                //结合filter过滤数字 小于或等于50的数字被过滤
                .filter(intPredicate)
                .peek(System.out::println).count();

    }
}
==>
true
------------------------------
59
55
99
88

习题一

image-20211206022256096

import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Predicate;

/**
 * @author : yingH
 * @create : 2021-12062:22
 * @details :
 */
public class LambdaTest4 {
    public static void main(String[] args) {
       int[] arr={1, 23, 4, 4, 22, 34, 45, 11, 33};
        System.out.println(Arrays.stream(arr).min());
        System.out.println(Arrays.stream(arr).distinct().map((i) -> i * 2).sum());
    }

}
===>
OptionalInt[1]
346

Stream 流

  • 元素序列:Stream 以序列的形式提供了特定类型的元素的集合。根据需求,它可以获得和计算元素,但不会储存任何元素。
  • 源:Stream 可以将集合、数组和 I/O 资源作为输入源。
  • 聚集操作:Stream 支持诸如 filtermaplimitreduce 等的聚集操作。
  • 流水技术:许多 Stream 操作返回了流本身,故它们的返回值可以以流水的行式存在。这些操作称之为中间操作,并且它们的功能就是负责输入、处理和向目标输出。collect() 方法是一个终结操作,通常存在于流水线操作的末端,来标记流的结束。
  • 自动迭代:Stream 的操作可以基于已提供的源元素进行内部的迭代,而集合则需要显式的迭代。
集合的接口有两个方法来产生流
  • stream():该方法返回一个将集合视为源的连续流。
  • parallelStream():该方法返回一个将集合视为源的并行流。
其他相关方法
  • forEach:该方法用于对 Stream 中的每个元素进行迭代操作。下面的代码段演示了如何使用 forEach 方法输出 10 个随机数。
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * @author : yingH
 * @create : 2021-12062:52
 * @details :
 */
public class StreamTest {
    public static void main(String[] args) {
     /*   Random random = new Random();
        //forEach:该方法用于对 Stream 中的每个元素进行迭代操作
        //random.ints().limit(10).forEach(System.out::println);
        System.out.println("---------------------");
        //map:该方法用于将每个元素映射到对应的结果上。
        List<Integer> numbers = Arrays.asList(2, 3, 3, 2, 5, 2, 7);
        List<Integer> squaresList=numbers.stream().map(i->i*i).distinct().collect(Collectors.toList());
        //distinct() 去重
        System.out.println("---------------------");

        //filter:该方法用于过滤满足条件的元素
        List<String>strings = Arrays.asList("efg", "", "abc", "bc", "ghij","", "lmn");
        strings.stream().filter(String-> strings.isEmpty()).count();
        System.out.println("---------------------");

        //limit:该方法用于减少 Stream 的大小。
        //random.ints().limit(10).forEach(System.out::println);

        //sorted:该方法用于对 Stream 排序。
        random.ints().limit(10).sorted().forEach(System.out::println);
        System.out.println("---------------------");

        //并行处理  ParallelStream 是 Stream 用于并行处理的一种替代方案。
        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("Filtered List: " + filtered);

        String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));

        System.out.println("Merged String: " + mergedString);*/

        //统计工具   Stream 处理完成后使用 Collector 来统计数据。
        List<Integer> numbers = Arrays.asList(2, 3, 3, 2, 5, 2, 7);

        IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

        System.out.println("Highest number in List : " + stats.getMax());
        System.out.println("Lowest number in List : " + stats.getMin());
        System.out.println("Sum of all numbers : " + stats.getSum());
        System.out.println("Average of all numbers : " + stats.getAverage());

    }
}

习题二

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : yingH
 * @create : 2021-12063:05
 * @details :
 */
public class StreamTest2 {
    public static void main(String[] args) {
        System.out.println("Using Java 7:");

        // 统计空字符串的数量
        List<String> strings = Arrays.asList("efg", "", "abc", "bc", "ghij","", "lmn");
        System.out.println("List: " +strings);
        long count = getCountEmptyStringUsingJava7(strings);

        System.out.println("Empty Strings: " + count);
        count = getCountLength3UsingJava7(strings);

        System.out.println("Strings of length 3: " + count);

        // 消除空字符串
        List<String> filtered = deleteEmptyStringsUsingJava7(strings);
        System.out.println("Filtered List: " + filtered);

        // 消除空字符串,同时使用逗号来连接
        String mergedString = getMergedStringUsingJava7(strings,", ");
        System.out.println("Merged String: " + mergedString);
        List<Integer> numbers = Arrays.asList(2, 3, 3, 2, 5, 2, 7);

        // 获得不同数字的平方的列表
        List<Integer> squaresList = getSquares(numbers);
        System.out.println("Squares List: " + squaresList);
        List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);

        System.out.println("List: " +integers);
        System.out.println("Highest number in List : " + getMax(integers));
        System.out.println("Lowest number in List : " + getMin(integers));
        System.out.println("Sum of all numbers : " + getSum(integers));
        System.out.println("Average of all numbers : " + getAverage(integers));


        // 输出10个随机数
        System.out.println("Random Numbers: ");
        Random random = new Random();

        for(int i=0; i < 10; i++){
            System.out.println(random.nextInt());
        }



        // 使用Java 8的新特性

        System.out.println("Using Java 8: ");
        System.out.println("List: " +strings);

        count = strings.stream().filter(string->string.isEmpty()).count();
        System.out.println("Empty Strings: " + count);

        count = strings.stream().filter(string -> string.length() == 3).count();
        System.out.println("Strings of length 3: " + count);

        filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList());
        System.out.println("Filtered List: " + filtered);

        mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("Merged String: " + mergedString);

        squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList());
        System.out.println("Squares List: " + squaresList);
        System.out.println("List: " +integers);

        IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics();

        // 输出结果
        System.out.println("Highest number in List : " + stats.getMax());
        System.out.println("Lowest number in List : " + stats.getMin());
        System.out.println("Sum of all numbers : " + stats.getSum());
        System.out.println("Average of all numbers : " + stats.getAverage());
        System.out.println("Random Numbers: ");

        random.ints().limit(10).sorted().forEach(System.out::println);

        // 并行处理
        count = strings.parallelStream().filter(string -> string.isEmpty()).count();
        System.out.println("Empty Strings: " + count);

    }

    //使用Java 7版本就提供的API来计算空串数量
    private static int getCountEmptyStringUsingJava7(List<String>strings){
        int count=0;
        for (String str:strings){
            if (str.isEmpty()){
                count++;
            }
        }
        return count;
    }

    // 使用Java 7版本就提供的API来计算长度为3字符的字符串数量
    private static int getCountLength3UsingJava7(List<String> strings){
        int count=0;
        for (String Str:strings){
            if (Str.length()==3){
                count++;
            }
        }
        return count;
    }

    // 使用Java 7版本就提供的API来删除空串
    private static List<String> deleteEmptyStringsUsingJava7(List<String>strings){
        ArrayList<String> filteredList  = new ArrayList<>();
        for (String str:strings){
            if (!str.isEmpty()){
                filteredList.add(str);
            }
        }
        return filteredList;
    }

    // 使用Java 7版本就提供的API来获取合并后的字符串
    public static String getMergedStringUsingJava7(List<String>strings,String separator){
        StringBuilder stringBuilder = new StringBuilder();
        for (String str:strings){
            if (!str.isEmpty()){
                stringBuilder.append(str);
                stringBuilder.append(separator);
            }
        }
        String mergedString  = stringBuilder.toString();
        return mergedString.substring(0,mergedString .length()-2);
    }

    // 自定义的用于计算数字的平方的方法
    public static List<Integer> getSquares(List<Integer> numbers){
        ArrayList<Integer> squaresList  = new ArrayList<>();
        for (Integer number:numbers){
            Integer square = new Integer(number.intValue() * number.intValue());
            if (!squaresList.contains(square))
                squaresList.add(square);
        }
        return squaresList;
    }

    // 自定义的用于获得List中最大值的方法
    private static int getMax(List<Integer> numbers){
        int max=numbers.get(0);
        for (int i = 0; i < numbers.size(); i++) {
            Integer n = numbers.get(i);
            if (n.intValue()>max)
                max=n.intValue();
        }
        return max;
    }

    // 自定义的用于获得List中最小值的方法
    public static int getMin(List<Integer> numbers){
        Integer min = numbers.get(0);
        for (int i = 0; i < numbers.size(); i++) {
            Integer n = numbers.get(i);
            if (n.intValue()<min)
                min=n.intValue();
        }
        return min;
    }

    // 自定义的用于获得List中各个数字的和的方法
    private static int getSum(List<Integer> numbers){
        int sum = (numbers.get(0));
        for (int i = 1; i <numbers.size() ; i++) {
            sum+=numbers.get(i);
        }
        return sum;
    }

    // 自定义的用于获得List中各个数字的平均值的方法
    private static int getAverage(List<Integer> numbers){
        return getSum(numbers)/numbers.size();
    }

}


==>
Using Java 7:
List: [efg, , abc, bc, ghij, , lmn]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [efg, abc, bc, ghij, lmn]
Merged String: efg, abc, bc, ghij, lmn
Squares List: [4, 9, 25, 49]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9
Random Numbers: 
1335013981
-669086334
-1977946920
1909214582
1757036680
885701689
89681016
-398447469
-1947386503
-81947933
Using Java 8: 
List: [efg, , abc, bc, ghij, , lmn]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [efg, abc, bc, ghij, lmn]
Merged String: efg, abc, bc, ghij, lmn
Squares List: [4, 9, 25, 49]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9.444444444444445
Random Numbers: 
-1942742109
-1912651435
-1774773560
-1490197790
-478437477
-345688376
-245211403
403256953
1221745667
2034137589
Empty Strings: 2

FlatMap

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

import java.util.Arrays;
import java.util.stream.Stream;

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将一种类型的流 转换为另外一个类型的流  这里转换成了String[]流
                //这并不是我们想要的,我们想要的是Stream<String>,而不是Stream<String[]>
                .map(v -> v.split(" "));
        Stream<String> flatMapStream = stringStream2
                //Arrays.stream将数组转换成了流 这里将分割后的String[],转换成了Stream<String>,但是我们前面定义了三个字符串
                //所以这里将产生三个Stream<String>,flatMap用于将三个流合并成一个流
                .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;@2d98a335
[Ljava.lang.String;@16b98e56
[Ljava.lang.String;@7ef20235
flatMapStream打印:
shi
yan
shi
yan
lou
lou
yan
shi
练习题:合并流

image-20211206033237415

import java.util.stream.Stream;

public class MergerStream {
    public static void main(String[] args) {
        Stream<Integer> stream1 = Stream.of(1, 2, 3);
        Stream<Integer> stream2 = Stream.of(4, 5, 6);
        Stream<Integer> stream3 = Stream.of(7, 8, 9);
        Stream<Integer> mergerStream = Stream.of(stream1, stream2, stream3).flatMap((i) -> i);
        mergerStream.forEach(System.out::print);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值