Java8 lammda表达式,方法引用,stream Api以及Optional类的使用

一,lammda表达式的使用

函数式接口:就是一个接口中只有一个抽象方法,lammda表达式其实就是创建一个接口实例,并对这个抽象方法进行重写

java8内置四大核心函数式接口
​ java.util.function包下的接口都是“无意义”的,这个“无意义”并不是说它们没有存在的意义,而是说它们都必须放到具体的语境中去才会真正的意义。或者说,它们是“非典型”的Java API就体现在,它们自己是没有语境(Context)的,它们实际上可以说就是为Lambda表达式而存在的——你不需要了解它叫什么(匿名的),它们是作为参数在对象的方法的中传递的。

​ 其实,所有java.util.function包下的接口的方法名,我们都不必关心,因为当我们用它们的时候,压根不会去显式地调用它们,方法名也是“无意义”的,它们只是方便大家去理解他的用途。但是,方法的参数和返回值是需要我们关心和注意的。

function包下总共有43个接口,可分为这四类核心函数式接口:Function、Supplier、Consumer、Predicate。

1.消费型接口
Consumer:消费型接口 单一抽象方法为:void accept(T t);

  • 作用:消费某个对象**(传入一个泛型参数,不返回任何值)**

  • 举例:forEach: Iterable接口的foeEach方法 需要传入Consumer,大部分集合类都实现了该接口,用于返回Iterator对象进行迭代。

2.供给型接口

Supplier:供给型接口 T get();

  • 作用:创建一个对象(工厂类)(不传入参数,返回一个值)
  • 举例:Optional.orElseGet(Supplier<? extends T>):当this对象为null,就通过传入supplier创建一个T返回。(Optional类是一种容器对象,要么包装值,要么为空)

3.函数式接口

Function<T,R>:函数型接口 R apply(T t);

  • 作用:实现一个“一元函数”,即传入一个值经过函数的计算返回另一个值。(传入一个参数,返回一个值)

4.断言型接口
Predicate:断言型接口 单一抽象方法: boolean test(T t);

作用:判断对象是否符合某个条件**(传入一个参数,返回一个布尔值)**
举例:主要用于流的筛选。给定一个包含若干项的流,Stream接口的filter方法传入一个Predicate并返回一个新的流,它仅包含满足给定谓词的项。

 

方法引用:

方法引用就是lammda表达式的简化版,就是说函数式接口中抽象方法已经有类去实现了,咱们就可以直接调用这个方法

主要有三种表现形式:

1)引用特定对象的实例方法:对象::实例方法名(object::instanceMethod)

(x)->System.out.println(x);
简化为:System.out::println

2)引用静态方法:类::静态方法名(Class::staticMethod)

()->Math.random();
简化为:Math::random


3)调用特定类型的任意对象的实例方法: 类::实例方法名(Class::instanceMethod ):这个比较特殊,可能接口中的抽象方法和引用方法格式不同,而是接口中的抽象方法的第一个参数如果可以调用这个方法,那么就可以通过这个方法的类名加实例方法去调用引用方法

x->x.length();
简化为:String::length


注意:如果通过类名引用一个传入多个参数的方法,则接口中的抽象方法的第一个参数将作为方法的调用者,其他元素作为方法的参数,可以使用ClassName::instanceMethod 。

(o1,o2)->o1.compareTo(o2);
简化为:String::compareTo


注意:需要实现的接口中的抽象方法的 参数列表与返回值类型 要与 当前调用的方法的参数列表、返回值类型保持一致

StreamApi的使用:检索集合或者数组

特点:1.与集合不同,集合是与内存打交道,而Stream Api是与cpu打交道

           2.延迟执行,只有在需要结果的时候才会执行,或者执行了终止操作的时候才会执行

大概步骤就是:

  1.获取stream实例对象

    通过集合获取stream对象:集合实例.stream();

    通过数组获取stream对象:Arrays.stream(数组实例)

    通过Stream类下自带的of方法,of的参数就是任意元素

  2.中间操作

   (1)筛选与切片

    filter(predicate p):对元素进行筛选

   limit(n) :获取前n条数据

   skip(n) : 跳过前n条数据,返回后边的数据

   distinct():元素去重

    (2)映射

     map(Function  f):对元素进行修改或者操作,返回一个新的stream实例

     flatMap(Function f):与map的区别就是,在操作中返回的新的stream实例,里边的元素应该还是stream实例,如果是map的话就会stream里边嵌套stream,如果这flatmap,就会把里边的stream拆解,追加到外边的stream中

    (3)排序

     Sorted():可以是自然排序,如果元组本身就可以直接排序就可以使用自然排序

     Sorted(Comparator<T> c):可以自己进行定制,如果是对象,要根据某个元素排序就需要用到定制排序,一下就是根据对象年龄参数进行升序排序

  3.终止操作

  allMatch(predicate p):检查是否匹配所有元素

  anyMatch(predicate p)检查是否至少匹配一个元素

  noneMatch(predicate p)检查是否没有匹配的元素

  findFirst()返回第一个元素

  findany()返回任意元素

  count()返回元素总个数

   max(Comparator c)返回流中最大值

   min(Comparator c)返回流中最小值

forEach(Consumer c) 内部迭代

归约结束操作:

reduce(T 起始值,BinaryOperator),这里可以设置起始值,将流中的元素反复结合起来

eg:list.stream().reduce(0,Integer::Sum)

reduce(BinaryOperator) 不设置起始值,求元素的和

收集结束操作:

collect(Collector c)

eg:list.stream().collect(Collector.Toset)

list变换map的常用操作:

 //以brand和price属性分别作为key和value创建map,若集合中存在key重复的元素,就取后一个
        Map<String, BigDecimal> collect = cars.stream().collect(Collectors.toMap(Car::getBrand, Car::getPrice, (x, y) -> y));
        //以brand为key,将集合分组,每个brand对应一个Car集合
        Map<String, List<Car>> collect1 = cars.stream().collect(Collectors.groupingBy(Car::getBrand));
        //将集合按是否满足partitioningBy中的断言函数为标准,分成两个集合
        Map<Boolean, List<Car>> bn = cars.stream().collect(Collectors.partitioningBy(k -> "BMW".equals(k.getBrand())));

Collector中的常用方法:

/**
     * 返回List集合
     * toList
     */
    @Test
    public void stream1(){
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
        System.out.println(integers);
        List<Integer> collect = integers.stream().map(x -> x * x).collect(Collectors.toList());
        System.out.println(collect);
    }
    /**
     * 返回Set集合
     * toSet
     */
    @Test
    public void stream3(){
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
        System.out.println(integers);
        Set<Integer> collect = integers.stream().filter(value -> value > 2).collect(Collectors.toSet());
        System.out.println(collect);
    }

    /**
     * counting
     * 计算元素数量
     */
    @Test
    public void stream4(){
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
        System.out.println(integers);
        Long collect = integers.stream().collect(Collectors.counting());
        System.out.println(collect);
        System.out.println(integers);
    }

    /**
     * maxBy
     * 取最大值【naturalOrder自然排序】
     */
    @Test
    public void stream5(){
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
        System.out.println(integers);
        Integer integer = integers.stream().collect(Collectors.maxBy(Comparator.naturalOrder())).get();
        System.out.println(integer);
        System.out.println(integers);
    }
    /**
     * minBy
     * 取最小值【naturalOrder自然排序】
     */
    @Test
    public void stream6(){
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
        System.out.println(integers);
        Integer integer = integers.stream().collect(Collectors.minBy(Comparator.naturalOrder())).get();
        System.out.println(integer);
        System.out.println(integers);
    }

    /**
     * partitioningBy
     * 用于将一个集合划分为2个集合并将其添加到映射中集合中,
     * 满足给定条件的划分一个集合,并以true为key
     * 不满足给定条件的划分一个集合,并以false为key
     */
    @Test
    public void stream7(){
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,6);
        System.out.println(integers);
        Map<Boolean, List<Integer>> collect = integers.stream().collect(Collectors.partitioningBy(v -> (int) v > 3));
        System.out.println(collect);
        System.out.println(integers);
    }

    /**
     * joining
     * 连用指定的字符串连接集合内的元素
     * 结合内元素须为String类型
     */
    @Test
    public void stream8(){
        List<String> integers = Arrays.asList("1","2");
        String collect = integers.stream().collect(Collectors.joining(","));
        System.out.println(collect);
        //用指定的字符串连接集合内的元素,并在首尾加上指定字符
        String collect2 = integers.stream().collect(Collectors.joining(",","《","》"));
        System.out.println(collect2);
        //用指定的字符串连接int类型集合内的元素
        List<Integer> integers3 = Arrays.asList(1,1);
        String collect3 = integers3.stream().map(a-> String.valueOf(a) ).collect(Collectors.joining(","));
        System.out.println(collect3);
    }

    /**
     * 集合的平均值
     * averagingLong
     * averagingInt
     * averagingDouble
     */
    @Test
    public void stream9(){
        //long类型求平均值
        List<Long> longValues = Arrays.asList(100l,200l,300l);
        Double d1 = longValues
                .stream()
                .collect(Collectors.averagingLong(x -> x * 2));
        System.out.println("long类型求平均值:"+d1);
        //int类型求平均值
        List<Integer> intValues = Arrays.asList(12,30,45);
        Double d2 = intValues
                .stream()
                .collect(Collectors.averagingInt(x->x));
        System.out.println("int类型求平均值:"+d2);
        //double类型求平均值
        List<Double> doubleValues = Arrays.asList(1.1,2.0,3.0,4.0,5.0,5.0);
        Double d3 = doubleValues
                .stream()
                .collect(Collectors.averagingDouble(x->x));
        System.out.println("double类型求平均值:"+d3);
    }

    /**
     * 求和
     * summingLong
     * summingInt
     * summingDouble
     */
    @Test
    public void stream10(){
        //long类型求平均值
        List<Long> longValues = Arrays.asList(100l,200l,300l);
        Long d1 = longValues
                .stream()
                .collect(Collectors.summingLong(x -> x));
        System.out.println("long类型求和:"+d1);
        //int类型求平均值
        List<Integer> intValues = Arrays.asList(12,30,45);
        Integer d2 = intValues
                .stream()
                .collect(Collectors.summingInt(x->x));
        System.out.println("int类型求和:"+d2);
        //double类型求平均值
        List<Double> doubleValues = Arrays.asList(1.1,2.0,3.0,4.0,5.0,5.0);
        Double d3 = doubleValues
                .stream()
                .collect(Collectors.summingDouble(x->x));
        System.out.println("double类型求求和:"+d3);
    }

    /**
     * 汇总整数
     * 得到平均值、最小值、最大值、所有值的计数和总和。
     */
    @Test
    public void stream11(){
        List<Integer> intValues = Arrays.asList(12,30,45);
        IntSummaryStatistics collect = intValues
                .stream()
                .collect(Collectors.summarizingInt(x -> x));
        System.out.println(collect);
    }

    /**
     *
     * 创建Map
     * toMap
     * Function.identity()指向集合中的值
     */
    @Test
    public void stream12(){
        List<String> integers = Arrays.asList("dsf","sfsf");
        Map<String, Integer> collect = integers.stream().collect(Collectors.toMap(item -> item, String::length));
        System.out.println(collect);
        Map<String, Integer> collect2 = integers.stream().collect(Collectors.toMap(Function.identity(), String::length));
        System.out.println(collect2);
        //去重创建map【map中key唯一,不可重复】
        List<String> strings = Arrays.asList("dsf","sfsf","ggfdd","sfsf");
        Map<String, Integer> collect3 = strings.stream().collect(Collectors.toMap(item -> item, String::length,(i1,i2)->i1));
        System.out.println(collect3);
    }
 	/**
     * 分组函数
     * GroupingBy
     */
    @Test
    public void stream13(){
        //分组
        List<String> strings = Arrays.asList("alpha","beta","gamma");
        final Map<Integer, List<String>> collect = strings.stream().collect(Collectors.groupingBy(String::length));
        System.out.println(collect);
        //分组求和
        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map =  new HashMap<>();
        map.put("name","张三");
        map.put("money","25");
        Map<String, String> map2 =  new HashMap<>();
        map2.put("name","张四");
        map2.put("money","50");
        Map<String, String> map3 =  new HashMap<>();
        map3.put("name","张三");
        map3.put("money","30");
        list.add(map);
        list.add(map2);
        list.add(map3);
        Map<String, Integer> name = list.stream().collect(Collectors.groupingBy(item -> item.get("name"), Collectors.summingInt(item -> Integer.parseInt(item.get("money")))));
        System.out.println(name);
    }

}
 

三,Optional类的使用

 可以防止空指针的发生

获取optional类实例的三种方式:

Optional.of(T f):创建一个Optional实例,t必须为空

Optional.empty():创建一个空的Optional实例

Optional.ofNullable(T t):t可以为null

optional类实例方法的使用:

orElse(T t):调用者如果为空就使用参数中的实例

eg:Optional<Boy>  o=Optional.ofNullable(new Boy());

       Boy b= o.orElse(new BOY);//假如o为null,就使用后边的对象为boy赋值


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EntyIU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值