JDK8新特性——Lambda

10 篇文章 0 订阅

JDK8新特性——Lambda

1.Lambda表达式

特殊的匿名内部类,语法更加简洁。

Lambda表达式允许把函数作为一个方法的参数传递,将代码像数据一样传递。

1.1基本语法:

<函数式接口><变量名>=(参数1,参数2,...)->{
//方法体
}

函数式接口是被注解@FunctionalInterface标注的接口:
如下是一个自定义的函数式接口:

package com.jzt.lambda;

/**
 * 自定义一个函数式接口
 */
@FunctionalInterface
public interface IUsb {
    void work();
}

1.2操作符

Lambda表达式引入了新的操作符:->(箭头操作符),->将表达式分为两个部分:

  • 左侧:(参数1,参数2…)标识参数列表

  • 右侧:{}内部是方法体。

1.3注意事项

  • 形参列表的数据类型会自动推断;
  • 如果形参列表为空,只需要写()即可;
  • 如果形参只有一个,()可以省略,只需要参数的名称即可
  • 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省略{},则需要同时省略return,且执行语句也必须保证只有一句。
  • Lambda表达式不会生成单独的内部类文件。

1.3举例

package com.jzt.lambda;

import java.util.Comparator;
import java.util.TreeSet;

/**
 * 演示Lambda表达式
 */
public class Demo1 {
    public static void main(String[] args) {
        Runnable runnable = new Runnable(){
            @Override
            public void run() {
                System.out.println("子线程运行了");
            }
        };
        new Thread(runnable).start();
        //使用Lambda表达式来简化
        Runnable runnable2 = ()->System.out.println("子线程运行了");

        new Thread(()->System.out.println("子线程运行了")).start();

        //例子2Comparator比较器
        Comparator<String> comparator = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length() - o2.length();
            }
        };

        TreeSet<String> treeSet = new TreeSet<>(comparator);

        //使用Lambda表达式简化
        Comparator<String> comparator2 = (o1, o2)->o1.length() - o2.length();
        TreeSet<String> treeSet2 = new TreeSet<>(comparator2);
    }
}

2.函数式接口

2.1概述

如果一个接口只有一个抽象方法,则该接口称作为函数式接口。

函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。

通过**@FunctionalInterface**注解可以检测一个接口是否为函数式接口。

package com.jzt.lambda;

@FunctionalInterface
public interface IUsb {
    void work();
}package com.jzt.lambda; @FunctionalInterface public interface IUsb {    void work(); }

2.2常见的函数式接口

函数式接口参数类型返回类型说明
Consumer消费型接口Tvoidvoid accept(T t);对象类型为T的对象应用操作
Supplier供给型接口TT get();返回类型为T的对象
Function<T,R>函数型接口TRR apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象
Predicate断言型接口Tbooleanboolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。

2.3函数式接口的使用

2.3.1消费型接口
package com.jzt.lambda;

import java.util.function.Consumer;

/**
 * 演示函数式接口的使用1
 *  消费型接口
 */
public class Demo3 {
    public static void main(String[] args) {
        //使用匿名内部类
        Consumer<Double> consumer = new Consumer<Double>() {
            @Override
            public void accept(Double aDouble) {
                System.out.println("消费了:"+aDouble);
            }
        };
        shopping(consumer,1000.0);

        //使用Lambda表达式
        Consumer<Double> consumer1 = aDouble->System.out.println("消费了:"+aDouble);
        shopping(consumer1, 2000.0);

        shopping(aDouble->System.out.println("消费了:"+aDouble), 3000.0);
    }

    //Consumer消费型接口
    public static void shopping(Consumer<Double> consumer, Double money){
        consumer.accept(money);
    }
}
2.3.2供给型接口
package com.jzt.lambda;

import java.util.Arrays;
import java.util.Random;
import java.util.function.Supplier;

/**
 * 供给型接口演示
 */
public class Demo4 {

    public static void main(String[] args) {
        //使用匿名内部类的方式
        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(100);
            }
        };

        int[] result = getNums(supplier, 5);
        System.out.println(Arrays.toString(result));

        //使用Lamdba表达式
        Supplier<Integer> supplier2 = () -> new Random().nextInt(100);
        int[] result2 = getNums(supplier2, 10);
        System.out.println(Arrays.toString(result2));

        //在简化
        int[] result3 = getNums(() -> new Random().nextInt(100), 15);
        System.out.println(Arrays.toString(result3));
    }

    public static int[] getNums(Supplier<Integer> supplier, int count){
        int[] arr = new int[count];
        for(int i = 0; i < count; i++){
            arr[i] = supplier.get();
        }
        return arr;
    }
}
2.3.3函数型接口
package com.jzt.lambda;

import java.util.function.Function;

/**
 * 函数式接口演示
 */
public class Demo5 {
    public static void main(String[] args) {
        //匿名内部类的方式
        Function<String, String> function = new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();//全部转为大写
            }
        };
        String result = handlerStr(function, "abc");
        System.out.println(result);

        //使用Lambda表达式
        String result2 = handlerStr(s -> s.trim(), "  abc  ");//去除空格
        System.out.println(result2);
    }

    public static String handlerStr(Function<String, String> function, String str){
        return function.apply(str);
    }

}

4)断言型接口

package com.jzt.lambda;

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

/**
 * 演示断言型接口
 */
public class Demo6 {

    public static void main(String[] args) {
        //匿名内部类方式
        Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("Test");//是否已Test开头
            }
        };
        List<String> list = new ArrayList<>();
        list.add("Test_zhangsan");
        list.add("tt_lisi");
        list.add("Test_wangwu");
        list.add("zhaoliu");
        List<String> result = filterNames(predicate, list);
        System.out.println(result);

        //Lambda表达式
        List<String> result2 = filterNames(s -> s.contains("t"), list);//是否包含字符串t
        System.out.println(result2);
    }

    public static List<String> filterNames(Predicate<String> predicate, List<String> list){
        List<String> strList = new ArrayList<>();
        for(String str : list){
            if(predicate.test(str)){
                strList.add(str);
            }
        }
        return strList;
    }
}

3.方法引用

方法引用是Lambda表达式的一种简写形式。如果Lambda表达式中只是调用一个特定的已经存在的方法,则可以使用方法引用。

常见的形式:

  • 对象::实例方法,表示调用改对象实例方法
  • 类::静态方法,表示调用改类的静态方法
  • 类::实例方法,表示调用该类实例方法
  • 类::new,表示创建该类的一个对象
package com.jzt.lambda;

import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 演示方法引用
 * 1、对象::实例方法
 * 2、类::静态方法
 * 3、类::实例方法
 * 4、类::new
 */
public class Demo7 {

    public static void main(String[] args) {
        //1、对象::实例方法
        Consumer<String> consumer = s -> System.out.println(s);
        /*
         * 分析:
         *  1)Consumer接口只有void accept(T t)方法,
         *  2)System.out对象的方法public void println(String x),参数形式与Consumer接口的accept方法一致
         */
        //使用方法引用
        Consumer<String> consumer1 = System.out::println;

        //2、类::静态方法
        Comparator<Integer> comparator = (o1, o2) -> Integer.compare(o1, o2);
        /*
         * 分析:
         *  1)Comparator接口只有int compare(T o1, T o2);
         *  2)Integer类的方法public static int compare(int x, int y),
         *      参数形式与Comparator接口的compare方法一致,同时参数列表也是一致的
         */
        //使用方法引用
        Comparator<Integer> comparator1 = Integer::compare;

        //3、类::实例方法
        Function<User, String> function = s -> s.getName();
        /*
         * 分析:
         *  1)Function接口只有R apply(T t);
         *  2)等号右侧就是就是apply中传入的对象User调用自身的getName()方法,且返回值也是String
         */
        //方法引用
        Function<User, String> function1 = User::getName;
        System.out.println(function1.apply(new User("小明", 18)));

        //4、类::new
        Supplier<User> supplier = () -> new User();
        //方法引用
        Supplier<User> supplier2 = User::new;
        User user = supplier2.get();
        System.out.println(user);
    }
}

User类

package com.jzt.lambda;

public class User {

    private String name;

    private int age;

    public User() {
        super();
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

4.Stream流

流(Stream)中保存对集合或数组数据的操作。和集合类似,单机和中保存的是数据。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJYADxPO-1609056606099)(D:\data\youdaoNote\weixinobU7VjoqKsPIOC3vcNuosN7uJCCM\ac3aa22894e64e709be2ce3576e5013d\clipboard.png)]

4.1Stream特点

  • Stream自己不会存储元素;
  • Stream不会改变远对象,相反,他们会返回一个持有结果的新Stream。
  • Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

4.2Stream使用步骤

1)创建

新建一个流

2)中间操作

在一个或者多个步骤中,将初始化Stream转化到另一个Stream的中间操作

3)终止操作

使用一个种植操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,改Stream就不嗯能够使用了。

4.2.1创建Stream

创建Stream集中方式:

- 通过Collection对象的stream()或者parallelStream()方法;

- 通过Arrays工具类的stream()方法;

- 通过Stream接口的of()、iterate()、fenerate()方法;

- 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。

下面演示:

package com.jzt.lambda;

import java.util.*;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 演示创建Stream的四种方式:
 *  - 通过Collection对象的stream()或者parallelStream()方法;
 * - 通过Arrays工具类的stream()方法;
 * - 通过Stream接口的of()、iterate()、fenerate()方法;
 * - 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。
 */
public class Demo8 {
    public static void main(String[] args) {
        //1、通过Collection对象的stream()或者parallelStream()方法:
        System.out.println("--------------------------------------------");
        System.out.println("1、通过Collection对象的stream()或者parallelStream()方法:");
        List<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        //1)使用stream()方法
//        Stream<String> stream1 = list.stream();
        //遍历
//        stream1.forEach(s -> System.out.println(s));
        //方法引用的方式
//        stream1.forEach(System.out::println);
        //2)使用parallelStream()方法
        Stream<String> stream2 = list.parallelStream();
//        stream2.forEach(s -> System.out.println(s));
        stream2.forEach(System.out::println);

        //2、通过Arrays工具类的stream()方法
        System.out.println("--------------------------------------------");
        System.out.println("2、通过Arrays工具类的stream()方法");
        String[] arr = {"AAA","BBB","CCC"};
        Stream<String> stream3 = Arrays.stream(arr);
//        stream3.forEach(s -> System.out.println(s));
        stream3.forEach(System.out::println);

        //3、通过Stream接口的of()、iterate()、fenerate()方法
        System.out.println("--------------------------------------------");
        System.out.println("3、通过Stream接口的of()、iterate()、fenerate()方法;");
        //of方法
        Stream<Integer> stream4 = Stream.of(1,2,3,4,5);
//        stream4.forEach(s -> System.out.println(s));
        stream4.forEach(System.out::println);
        //iterate()方法,迭代流
        Stream<Integer> stream5 = Stream.iterate(0, x->x+2);
        stream5.limit(5).forEach(s-> System.out.println(s));
        //fenerate()方法,生成流
        Stream<Integer> stream6 = Stream.generate(()-> new Random().nextInt(10));
        stream6.limit(10).forEach(System.out::println);

        //通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。
        System.out.println("--------------------------------------------");
        System.out.println("通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。");
        IntStream stream7 = IntStream.of(100,200,300);
        stream7.forEach(System.out::println);
        //range()方法
        IntStream stream8 = IntStream.range(0, 10);
        stream8.forEach(System.out::println);
        //rangeClosed()方法
        IntStream stream9 = IntStream.rangeClosed(0, 10);
        stream9.forEach(System.out::println);
    }
}
4.2.2中间操作
  • filter过滤、limit限制、skip跳过、distinct去重、sorted排序

  • map

  • parallel

演示中间操作:

1)filter过滤、limit限制、skip跳过、distinct去重、sorted排序

package com.jzt.lambda;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * 演示中间操作
 *  - filter、limit、skip、distinct、sorted
 */
public class Demo9 {
    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        list.add(new User("zhangsan", 18));
        list.add(new User("lisi", 20));
        list.add(new User("wangwu", 22));
        list.add(new User("zhaoliu", 19));
        list.add(new User("heiqi", 25));
        //filter过滤
        System.out.println("------------filter---------------");
        list.stream()
            .filter(e -> e.getAge() >20)
            .forEach(System.out::println);

        //limit限制
        System.out.println("------------limit---------------");
        list.stream()
            .limit(3)
            .forEach(System.out::println);

        //skip跳过
        System.out.println("------------skip---------------");
        list.stream()
            .skip(1)
            .forEach(System.out::println);

        //distinct去重
        System.out.println("------------distinct---------------");
        //需要User重写equals和hashcode方法
        list.add(new User("zhangsan", 18));
        list.add(new User("heiqi", 25));
        list.stream()
            .distinct()
            .forEach(System.out::println);

        //sorted排序
        System.out.println("------------sorted---------------");
        list.stream()
            .sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()))
            .forEach(System.out::println);
    }
}

2)map

package com.jzt.lambda;

import java.util.ArrayList;
import java.util.List;

/**
 * 演示中间操作
 *  map 转换为map集合
 */
public class Demo10 {
    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        list.add(new User("zhangsan", 18));
        list.add(new User("lisi", 20));
        list.add(new User("wangwu", 22));
        list.add(new User("zhaoliu", 19));
        list.add(new User("heiqi", 25));
        //将list结合转为map
        list.stream()
            .map(e -> e.getName())
            .forEach(System.out::println);
    }
}

3)parallel 并行

package com.jzt.lambda;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 演示中间操作
 *  parallel并行
 */
public class Demo11 {
    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        for(int i = 0; i < 10000; i++){
            list.add(UUID.randomUUID().toString());
        }
        //使用串行的方式
        long start = System.currentTimeMillis();
        long count = list.stream().sorted().count();
        long end = System.currentTimeMillis();
        System.out.println(end - start);

        //使用并行的方式
        long start1 = System.currentTimeMillis();
        long count1 = list.parallelStream().sorted().count();
        long end1 = System.currentTimeMillis();
        System.out.println(end1 - start1);
    }
}

结果:

time:72
time1:17
4.2.3终止操作
  • forEach遍历、min最小值、max最大值、count计数

  • reduce规约、collect收集

演示操作:

package com.jzt.lambda;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 演示终止操作
 * - forEach遍历、min最小值、max最大值、count计数
 * - reduce规约、collect收集
 */
public class Demo12 {
    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        list.add(new User("zhangsan", 18));
        list.add(new User("lisi", 20));
        list.add(new User("wangwu", 22));
        list.add(new User("zhaoliu", 19));
        list.add(new User("heiqi", 25));
        //- forEach遍历、min最小值、max最大值、count计数
        //forEach遍历
        System.out.println("-----forEach遍历----------------");
        list.stream()
            .filter(e->{
                System.out.println("过滤了");
                return e.getAge() > 20;
            })
            .forEach(System.out::println);
        //min最小值
        //获取user集合中年龄最小值
        System.out.println("-----min最小值----------------");
        Optional<User> min = list.stream()
            .min((e1, e2)->Integer.compare(e1.getAge(),e2.getAge()));
        System.out.println(min.get());
        //max最大值
        //获取user中年龄最大值
        System.out.println("-----max最大值----------------");
        Optional<User> max = list.stream()
            .max((e1, e2)->Integer.compare(e1.getAge(),e2.getAge()));
        System.out.println(max.get());
        //count计数
        //获取user个数
        System.out.println("-----count计数----------------");
        long count = list.stream()
            .count();
        System.out.println(count);

        // - reduce规约、collect收集
        //reduce规约
        //计算所有user年龄和
        System.out.println("-----reduce规约----------------");
        Optional<Integer> sum = list.stream()
            .map(e->e.getAge())
            .reduce((x,y)->x+y);
        System.out.println(sum.get());
        //collect收集
        //收集所有user姓名,放入list结合中
        System.out.println("-----collect收集----------------");
        List<String> names = list.stream()
            .map(e->e.getName())
            .collect(Collectors.toList());
        System.out.println(names);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值