lambda表达式

lambda表达式

lambda表达式含义: Lambda 表达式(函数式编程)”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型, JDK8开始引入语法

这里我们拿个创建线程的例子给大家看清楚到底什么是lambda表达式:

普通创建

 Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0;i<10;i++){
                    System.out.println(i);
                }
            }
        });

lambda表达式写法

Thread t2 = new Thread(()->{
                for (int i = 0;i<10;i++){
                    System.out.println(i);
                }
        });

使用前提

  • 1.匿名内部类实现接口
  • 2.这个接口是函数式接口: 接口中只有一个抽象方法(可以包含默认方法和静态方法)我们可以给一个符合函数式接口添加@FunctionalInterface注解,这样就显式的指明该接口是一个函数式接口,如果不是,编译器会直接提示错误。
  • 3.作为方法参数使用

语法: (参数) -> { 要实现的那个方法的方法体 }

进一步简化方式:

  1. 如果方法有参数,参数类型可以省略
  2. 如果方法体只有一句代码, return关键字、;、{} 可以省略(必须一起省略)
  3. 如果方法中只有一个参数, () 可以省略

常用的函数式接口

1.Supplier接⼝

java.util.function.Supplier 接⼝仅包含⼀个⽆参的⽅法: T get() 。⽤来获取⼀个泛型参数指定类型的对象数据。由于这是⼀个函数式接⼝,这也就意味着对应的Lambda表达式需要“对外提供”⼀个符合泛型类型的对象数据。

public static Integer max01(Supplier<Integer> supplier){
       return supplier.get();
    }
    public static void main(String[] args) {
        Integer[] arr={12,15,180,99,102};
        Integer integer = max01(() -> {
            Integer max = arr[0];
            for (int i = 0; i < arr.length; i++) {
                if (arr[i] > max) {
                    max = arr[i];
                }
            }
            return max;
        });
        System.out.println(integer);
    }
//获取一个数组中的最大值

2.Consumer接⼝

java.util.function.Consumer 接⼝则正好与Supplier接⼝相反,它不是⽣产⼀个数据,⽽是消费⼀个数据,其数据类型由泛型决定,抽象方法:accept

 public static void print(Consumer<person> consumer01,Consumer<person> consumer02,person p){
        consumer01.andThen(consumer02).accept(p);
    }
    public static void main(String[] args) {
        person p = new person("张无忌", 18);
        print(T-> System.out.println(T.getName()+"是某某某的父亲"),T-> System.out.println(T.getName()+"今年"+T.getAge()+"岁"),p);
    }

3.Predicate接⼝

有时候我们需要对某种类型的数据进⾏判断,从⽽得到⼀个boolean值结果。这时可以使 java.util.function.Predicate 接⼝,抽象方法:test

//挑选数组中名字张开头和三个字组成的名字
public static void print(Predicate<person> predicate01,Predicate<person> predicate02,person[] p){
        for (person person : p){
        if(predicate01.and(predicate02).test(person)){
            System.out.println(person);
        }}
    }
    public static void main(String[] args) {
        person[] ps = {new person("张三丰",23),
                new person("张无忌",99),
                new person("沈腾",45),
                new person("张翠花",50),new person("张三",50)};
        print(t->{return t.getName().startsWith("张");},t->{return t.getName().length()==3;},ps);
    }

4.Function接⼝java.util.function.Function<T,R> 接⼝⽤来根据⼀个类型的数据得到另⼀个类型的数据(俗称为转换类型方法),前者称为前置条件,后者称为后置条件,抽象方法:apply

//把String类型转换为Date类型
public static Date transfer(Function<String, Date> function, String str){
        return function.apply(str);
    }
    public static void main(String[] args) {
        Date transfer = transfer((t) -> {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                return sdf.parse(t);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }, "2022-7-19 11:53:49");
        System.out.println(transfer);
    }

流的优点: 可以以更好的方式遍历数组或者集合,很大程度上简化lambda表达式代码。

Stream(流)是⼀个来⾃数据源的元素队列

  • 元素是特定类型的对象,形成⼀个队列。 Java中的Stream并不会存储元素,⽽是按需计算。
  • 数据源流的来源。可以是集合,数组等。

流的特征

  1. 流水线:中间操作都会返回流对象本身。这样多个操作可以串联成⼀个管道, 如同流式⻛格。这样做可以对操作进⾏优化,⽐如延迟执⾏和短路。
  2. 内部迭代:以前对集合遍历都是通过Iterator或者增强for的⽅式,显式的在集合外部进⾏迭代,这叫做外部迭代。Stream提供了内部迭代的⽅式,流可以直接调⽤遍历⽅法。

备注:“Stream流”其实是⼀个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。

使用流的步骤: 获取⼀个数据源→ 数据转换 → 执⾏操作获取想要的结果

获取⼀个数据源(获取流)

  1. 所有的 Collection 集合都可以通过 stream 默认⽅法获取流;

    List<String> list = List.of("张三丰", "杨洋", "迪丽热巴");
    Stream<String> stream1=list.stream();
    Set<String> set =Set.of("手机","电脑","电视");
    Stream<String> stream2=set.stream();
    Map<String,Integer> map = Map.of("被子",23,"笔",5);
    Stream<String> stream3=map.keySet().stream();
    Stream<Integer> stream4=map.values().stream();
    Stream<Map.Entry<String,Integer>> stream5=map.entrySet().stream();
    
  2. Stream 接⼝的静态⽅法 of 可以获取数组对应的流。

     Stream<String> stream7 =Stream.of("张三丰", "杨洋", "迪丽热巴");
    

    备注: of ⽅法的参数其实是⼀个可变参数,所以⽀持数组

String[] atrarry={"手机","电脑","电视"};
Stream<String> stream6 = Arrays.stream(atrarry);

常用方法

延迟⽅法:返回值类型仍然是 Stream 接⼝⾃身类型的⽅法,因此⽀持链式调⽤。(除了终结⽅法外,其余⽅法均为延迟⽅法。)

终结⽅法:返回值类型不再是 Stream 接⼝⾃身类型的⽅法,因此不再⽀持类似 StringBuilder 那样的链式调⽤。本⼩节中,终结⽅法包括 count 和 forEach ⽅法。

逐⼀处理: forEach

//逐一打印所有名字
public class Demo12StreamForEach {
 public static void main(String[] args) {
 Stream<String> stream = Stream.of("张⽆忌", "张三丰", "周芷若");
 stream.forEach(name-> System.out.println(name));
 }

过滤: filter:可以通过 filter ⽅法将⼀个流转换成另⼀个⼦集流。

//挑选张开头的姓名
public class Demo07StreamFilter {
 public static void main(String[] args) {
 Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
 Stream<String> result = original.filter(s -> s.startsWith("张"));
 }

映射: map:如果需要将流中的元素映射到另⼀个流中,可以使⽤ map ⽅法。

public class Demo08StreamMap {
 public static void main(String[] args) {
 Stream<String> original = Stream.of("10", "12", "18");
 Stream<Integer> result = original.map(str->Integer.parseInt(str));
 }

统计个数: count:正如旧集合 Collection 当中的 size ⽅法⼀样,流提供 count ⽅法来数⼀数其中的元素个数

public class Demo09StreamCount {
 public static void main(String[] args) {
 Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
 Stream<String> result = original.filter(s -> s.startsWith("张"));
 System.out.println(result.count()); // 2
 }

取⽤前⼏个: limit:limit ⽅法可以对流进⾏截取,只取⽤前n个。

public class Demo10StreamLimit {
 public static void main(String[] args) {
 Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
 Stream<String> result = original.limit(2);
 System.out.println(result.count()); // 2
 }

跳过前⼏个: skip:如果希望跳过前⼏个元素,可以使⽤ skip ⽅法获取⼀个截取之后的新流

 public static void main(String[] args) {
 Stream<String> original = Stream.of("张⽆忌", "张三丰", "周芷若");
 Stream<String> result = original.skip(2);
 System.out.println(result.count()); // 1
 }

组合: concat:如果有两个流,希望合并成为⼀个流,那么可以使⽤ Stream 接⼝的静态⽅法 concat

public class Demo12StreamConcat {
 public static void main(String[] args) {
 Stream<String> streamA = Stream.of("张⽆忌");
 Stream<String> streamB = Stream.of("张翠⼭");
 Stream<String> result = Stream.concat(streamA, streamB);
 }
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值