JDK1.8 新特性,lambda表达式,函数式编程,Stream API的总结以及应用

本文详细介绍了JDK1.8的三大核心特性:lambda表达式、StreamAPI和Optional类。通过示例展示了如何使用lambda简化匿名内部类,利用StreamAPI进行高效数据处理,以及Optional类如何避免空指针异常。同时,文中还涵盖了函数式接口、方法引用、流的操作(如过滤、映射、排序、收集)以及各种中间和终结操作的使用。
摘要由CSDN通过智能技术生成

JDK1.8新特性,自己学习总结了以下几点:

1. lambda表达式
2. 函数式接口
3. 强大的Stream API
4. Optional类

5. 测试类的完整代码

一、lambda表达式

适用于匿名内部类,简化代码,相当于语法糖;
函数式接口可以使用lambda表达式

lambda的使用:

语法 : () -> {};

比如:Runnable r= (o1,o2) -> {Integer.compare(o1,o2)};

  • 左边的: () 就是lambda的形参列表,该接口中方法的形参列表,参数类型可以省略,可以根据泛型推断出来,若该接口没有形参的话就是();
  • -> : lambda操作符 或者 箭头操作符
  • 最右边: {} 大括号中是我们重写的方法体;只有一条语句时可以省略掉{}
本质:作为接口的一个实例,匿名内部类;

因为适用于 函数式接口,只有一个方法的接口,既然只有一个方法,那么没必要告诉我方法的名称,我就可以省略方法名,只需要提供所必须的参数,以及重写的方法体就可以了,可以省略很多不必要的代码;

首先测试需要用到的类:
ShopCart类:

package com.xt.test;

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

public class ShopCart {
    private int id;
    private String cartName;

    private List<Goods> goodsList;

    @Override
    public String toString() {
        return "ShopCart{" +
                "id=" + id +
                ", cartName='" + cartName + '\'' +
                ", goodsList=" + goodsList +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getCartName() {
        return cartName;
    }

    public void setCartName(String cartName) {
        this.cartName = cartName;
    }

    public List<Goods> getGoodsList() {
        return goodsList;
    }

    public void setGoodsList(List<Goods> goodsList) {
        this.goodsList = goodsList;
    }

    {
        List<Goods> goodsList1=new ArrayList<>();
        Goods goods5 = new Goods(4,"荣耀10",10);
        Goods goods1 = new Goods(1,"小米",12);
        Goods goods2 = new Goods(2,"华为手机",10);
        Goods goods3 = new Goods(3,"锤子科技",8);
        Goods goods4 = new Goods(4,"荣耀8",15);

        goodsList1.add(goods1);
        goodsList1.add(goods2);
        goodsList1.add(goods3);
        goodsList1.add(goods4);
        goodsList1.add(goods5);
        this.goodsList=goodsList1;
    }

    public ShopCart(int id, String cartName, List<Goods> goodsList) {
        this.id = id;
        this.cartName = cartName;
        this.goodsList = goodsList;
    }

    public ShopCart() {
    }
}

商品类Goods:

package com.xt.test;

public class Goods {

    private int id;
    private String goodsName;

    private int num;

    public Goods(int id, String goodsName, int num) {
        this.id = id;
        this.goodsName = goodsName;
        this.num = num;
    }

    public Goods() {
    }

    @Override
    public String toString() {
        return "Goods{" +
                "id=" + id +
                ", goodsName='" + goodsName + '\'' +
                ", num=" + num +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public int hashCode() {
        return 1;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj==null && this==null){
            return true;
        }
        if  (! (obj instanceof Goods)){
            return false;
        }
        Goods goods = (Goods) obj;
        if (goods.getId()==this.getId()){
            if (goods.getGoodsName()==this.getGoodsName()){
                if (goods.getNum()==this.getNum()){
                    return true;
                }
            }
        }
        return false;
    }
}

1、写法一

lambda体 没有参数,只有一条执行语句,{} 可以省略

``

lambda体 没有参数,只有一条执行语句,{} 可以省略
 @Test
    public void normal(){
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("this is runnable");
            }
        };
        runnable.run();
        System.out.println("********************************");
        Runnable runnable1=() ->  System.out.println("lambda....");
        runnable1.run();
    }

这里的runnable是一个接口,函数式接口,只有一个方法,源码如下:

``

@FunctionalInterface 
@FunctionalInterface 
public interface Runnable {
/**
• When an object implementing interface Runnable is used
• to create a thread, starting the thread causes the object's
• run method to be called in that separately executing
• thread.
• 
• The general contract of the method run is that it may
• take any action whatsoever.
• 
• @see       java.lang.Thread#run() 
*/
public abstract void run();
}

2、写法二

lambda体 只有一条执行语句,有返回值,{} 和return可以省略;
``

 @Test
    public void test2(){
        Comparator<Integer> comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };
        int compare = comparator.compare(21, 34);
        System.out.println("compare = " + compare);
        System.out.println("*******************************");
        // lambda 表达式的写法
        Comparator<Integer> comparator1=(o1,o2) -> Integer.compare(o1,o2);
        int compare1 = comparator1.compare(20, 34);
        System.out.println("compare1 = " + compare1);
        System.out.println("*******************************");
        // 方法引用
        Comparator<Integer> comparator2=Integer ::compare;
        int compare2 = comparator2.compare(20, 34);
        System.out.println("compare2 = " + compare2);
    }

3、语法三

lambda体 有多个参数,有多条执行语句,有返回值,就按照正常的写,需要有return关键字;

@Test
public void test3(){
    Comparator<Integer> comparator=(o1,o2) ->{
        System.out.println("o1 = " + o1);
        System.out.println("o2 = " + o2);
        return o1.compareTo(o2);
    };
    int compare = comparator.compare(12, 34);
    System.out.println("compare = " + compare);
}

二、函数式编程

一个接口,只有一个抽象方法,就是函数式接口,重写时可以使用lambda表达式,
在接口上添加注解 @FunctionInterface ,表明该接口是函数式接口,不加也可以,但是加上编译器可以帮我们检验正确性,也就是加了注解,我们只能写一个抽象方法,写两个的话 会直接报错,编译不通过;
与@Override一样,加上可以帮助我们检验;
可以使用lambda表达式来创建该接口的对象; 而lambda表达式要用,一定得是函数式接口才可以;
下次改版能不能 这样,compare (o1,o2) ->{},那样就不会局限于函数式接口了;
简单的说:lambda表达式就是一个函数式接口的实例,它还是依托于对象上的,它还是一个对象,java是oop语言; 只要一个对象是函数式接口的实例,那么就可以用lambda表达式来表示;
所以以前用匿名实现类的表示的现在都也可以用lambda表达式来写;
在java.util.funcation的包中定义了丰富的函数式接口;

  • 1、四大核心核心函数式接口

  • 在这里插入图片描述

- 2、方法引用

方法引用的四种格式:

  • 对象 :: 方法
  • 类 :: 静态方法
  • 类 :: 非静态方法 —特殊,只有lambda中才可以这样使用
  • 构造器引用: 类 :: new – 相当于 new 类() 有参数无参数均可;根据函数式接口中有没有参数来定;
 @Test
    public void test2(){
       
        // lambda 表达式的写法
        Comparator<Integer> comparator1=(o1,o2) -> Integer.compare(o1,o2);
        int compare1 = comparator1.compare(20, 34);
        System.out.println("compare1 = " + compare1);
        System.out.println("*******************************");
        // 方法引用
        Comparator<Integer> comparator2=Integer ::compare;
        int compare2 = comparator2.compare(20, 34);
        System.out.println("compare2 = " + compare2);
    }

Integer的compare方法 传入的参数和 Comparator 的抽象方法 compare传入的参数是一致的,而且都有返回值,就可以使用 方法引用:
下面是Integer 中compare的源码

public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

三、Stream API --本身不存储数据,是来计算数据的

把真正的函数式编程风格引入到java中;
使用stream API 对集合数据进行操作,类似于使用SQL执行的数据库查询;
提供了一种高效的数据处理方式;
redis,mangodb等NOSQL的数据需要Java层面来处理;
Stream和Collection集合的区别,Collection是一种静态的内存数据结构,而Stream是有关于计算的;Collection主要是面向内存的,存储在内存中; 而Stream是面向CPU的,通过cpu实现计算;
总的来说,集合讲的是数据,Stream将的是计算;
注意:

  1. stream 自己不会存储数据;类似于迭代器,是来遍历集合的,本身不报保存数据;
  2. stream不会改变源对象,相反,他们会返回一个持有结果的新的stream;
  3. stream是延迟执行的,意味着会等到需要结果的时候才执行;

1、stream 操作的三个步骤

1.1 创建stream

一个数据源,如: 数组、集合 ;获取一个流

1.2 中间操作

一个中间操作链,对数据源的数据进行处理;

1.3 终止操作

一旦执行终止操作,就执行中间操作链,并产生结果,之后,不会再被使用;
在这里插入图片描述

2、流的分类

顺序流:stream,按照顺序拿,单线程
并行流:parallelStream,并行拿数据,多线程

3、创建stream

原数据: 这里使用的是购物车ShopCart,中存放的是id,购物车名称,商品列表,商品的列表如下:

{
        List<Goods> goodsList1=new ArrayList<>();
        Goods goods5 = new Goods(4,"荣耀10",10);
        Goods goods1 = new Goods(1,"小米",12);
        Goods goods2 = new Goods(2,"华为手机",10);
        Goods goods3 = new Goods(3,"锤子科技",8);
        Goods goods4 = new Goods(4,"荣耀8",15);
        goodsList1.add(goods1);
        goodsList1.add(goods2);
        goodsList1.add(goods3);
        goodsList1.add(goods4);
        goodsList1.add(goods5);
        this.goodsList=goodsList1;
    }

通过集合 Collection
通过数组 Arrays

  @Test
    public void testStream(){
        ShopCart shopCart = new ShopCart();
        List<Goods> goodsList = shopCart.getGoodsList();
        //创建stream,支持泛型,基本类型,数组
        //创建stream,串行的
        Stream<Goods> stream = goodsList.stream();
        // 创建并行的stream
        Stream<Goods> goodsStream = goodsList.parallelStream();
        //通过数组 Array
        Goods goods1 = new Goods(1001, "小米", 12);
        Goods goods2 = new Goods(1002, "华为", 5);
        Goods arr[]={goods1,goods2};
        Stream<Goods> stream1 = Arrays.stream(arr);
    }

通过Sream 的of

// 通过 stream 的 of
        Stream<Integer> integerStream = Stream.of(1, 3, 5, 6, 7, 12);

无限流:迭代 iterate,生成generate

  // 无限流
    @Test
    public void test4(){
        // 输出 10个偶数,第一个supply,第二个是限制个数,第三个是 消费者打印出来结果,
        Stream.iterate(0,num -> num+2).limit(10).forEach(System.out::println);
    }

4、中间操作–筛选于切片

1)筛选–filter

//筛选与切片

   @Test
    public void test5(){
        ShopCart shopCart = new ShopCart();
        List<Goods> goodsList = shopCart.getGoodsList();
        Stream<Goods> stream = goodsList.stream();
        // 过滤,filter 接收lambda,返回boolean,从流中过滤某些元素,集合中商品goods库存num>10的
        stream.filter(goods -> goods.getNum()>10).forEach(System.out::println);
    }

2)截断–limit

 //筛选与切片
    @Test
    public void test5(){
        ShopCart shopCart = new ShopCart();
        List<Goods> goodsList = shopCart.getGoodsList();
        Stream<Goods> stream = goodsList.stream();
        // 过滤,filter 接收lambda,返回boolean,从流中过滤某些元素,集合中商品goods库存num>10的
        stream.filter(goods -> goods.getNum()>10).forEach(System.out::println);
        System.out.println("************************************");
        // 截断流,不超过指定的数量
        goodsList.stream().limit(3).forEach(System.out::println);
    }

// 输出结果

Goods{id=1, goodsName='小米', num=12}
Goods{id=4, goodsName='荣耀', num=15}
************************************
Goods{id=1, goodsName='小米', num=12}
Goods{id=2, goodsName='华为', num=10}
Goods{id=3, goodsName='锤子', num=8}

3)跳过 skip,跳过前n个的流,若流中元素不足n个,则返回null

```java
 // 跳过 skip,
        goodsList.stream().skip(2).forEach(System.out::println);

输出结果是:

Goods{id=3, goodsName='锤子', num=8}
Goods{id=4, goodsName='荣耀', num=15}

4)distinct 筛选,通过流所生产的hashcode() 和equals(0 去除重复元素

``

 //筛选,需要重写hashcode和equals方法
        goodsList.add(new Goods(2,"华为",10));
        goodsList.add(new Goods(2,"华为",10));
        goodsList.add(new Goods(2,"华为",10));
        goodsList.stream().distinct().forEach(System.out::println);

goods类重写hashcode和equals方法

 @Override
    public int hashCode() {
        return 1;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj==null && this==null){
            return true;
        }
        if  (! (obj instanceof Goods)){
            return false;
        }
        Goods goods = (Goods) obj;
        if (goods.getId()==this.getId()){
            if (goods.getGoodsName()==this.getGoodsName()){
                if (goods.getNum()==this.getNum()){
                    return true;
                }
            }
        }
        return false;
    }

输出结果:

Goods{id=1, goodsName='小米', num=12}
Goods{id=2, goodsName='华为', num=10}
Goods{id=3, goodsName='锤子', num=8}
Goods{id=4, goodsName='荣耀', num=15}

5、映射 map–对应数学中的映射 ,1->1,2->4,3->9

一个key映射一个value,一个aa映射一个AA,可以用来替换数据库中的某些元素,集体更换,就可以使用到map映射;
概念:接收一个函数作为参数,将元素转换为其它形式或者提取信息;

5.1 map 相当于list中的add

  @Test
    public void test6(){
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(String::toUpperCase).forEach(System.out::println);
    }

输出结果:遍历集合list,将小写转换为大写

AA
BB
CC
DD
例子2) 将商品映射为对应的名称,然后筛选名称>3的
  //获取商品名称大于3的 ,使用map映射 ,将商品对象映射为商品名称,  首先映射,然后
        List<Goods> goodsList = new ShopCart().getGoodsList();
        Stream<String> stringStream = goodsList.stream().map(Goods::getGoodsName).filter(str -> str.length() > 3);
        stringStream.forEach(System.out::println);

输出结果:

华为手机
锤子科技

5.2 flatMap --相当于list中的addAll

接收一个函数作为参数,将其中的每个值转换为另一个流,然后把所有流进行操作,得到的结果都是单个元素,不存在[1,2,3,[5,6,7]] 集合套集合的情况;而是[1,2,3,5,6,7]
首先定义一个函数,将字符串转换为一个character的 stream流

 // 将字符串 转换为字符的stream流
    public static Stream<Character> fromStringToStream(String str){
        char[] charArray = str.toCharArray();
        List<Character> list=new ArrayList();
        for (Character c:charArray
             ) {
            list.add(c);
        }
        return list.stream();
    }

然后 flatMap,将集合中的string元素按照上面的函数,将其中的元素都拆分为character,作为一个新的集合,新的集合存放的是character

  @Test
    public void test6(){
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        // flatmap ,相当于list.addAll
        list.stream().flatMap(StreamTest::fromStringToStream).forEach(System.out::println);
    }

输出结果:将string类型的集合打散,新的集合中存放的是character元素

a
a
b
b
c
c
d
d

6、排序 sorted

  • 基本数据类型的排序–使用默认的sorted
  • 自定义对象的排序–需要将comparator比较器作为参数传入sorted,使用lambda表达式来实现
@Test
    public void test7(){
        // 1. 基本数据类型的排序
        List<Integer> integerList = Arrays.asList(1, 4, 6, 3, 8, 2);
        integerList.stream().sorted().forEach(System.out::println);
        // 对象的排序,商品的数量排序 ,,在数量相同的情况下 id 倒序
        List<Goods> goodsList = new ShopCart().getGoodsList();
        goodsList.stream().sorted( (g1,g2) -> {
            int i = Integer.compare(g1.getNum(), g2.getNum());
            if (i!=0){
                return i;
            }
            return -Integer.compare(g1.getId(),g2.getId());
        } ).forEach(System.out::println);
    }

输出结果:

1
2
3
4
6
8
Goods{id=3, goodsName='锤子科技', num=8}
Goods{id=4, goodsName='荣耀10', num=10}
Goods{id=2, goodsName='华为手机', num=10}
Goods{id=1, goodsName='小米', num=12}
Goods{id=4, goodsName='荣耀8', num=15}

Integer::compare 是在e1和e2是Integer的情况下可以用,这里e1是对象,不能直接用

7、匹配与查找

// 匹配与查找
    @Test
    public void test8(){
        List<Goods> goodsList = new ShopCart().getGoodsList();
        // 1. allMatch  检查是否匹配所有元素,是否购物车 商品数量都大于 10
        boolean allMatch = goodsList.stream().allMatch(goods -> goods.getNum() > 10);
        System.out.println("allMatch = " + allMatch);
        // 2. anyMatch 检查至少匹配一个元素  数量>10的
        boolean anyMatch = goodsList.stream().anyMatch(goods -> goods.getNum() > 10);
        System.out.println("anyMatch = " + anyMatch);
        // 3. noneMatch 检查是否有不存在在 小 开头的商品,如果有存在以 ‘小’ 开头 或者其它条件,比如包含contains,以小 结尾  endWith
        boolean noneMatch = goodsList.stream().noneMatch(goods -> goods.getGoodsName().startsWith("小"));
        System.out.println("noneMatch = " + noneMatch);
        // 4. findFirst 查找第一个元素
        Optional<Goods> first = goodsList.stream().findFirst();
        System.out.println("first.get() = " + first.get());
        
        // 5. findAny 随机查找一个元素
        Optional<Goods> any = goodsList.parallelStream().findAny();
        System.out.println("any.get() = " + any.get());
        // 6. count 统计个数 ,可以先筛选,后统计; 统计数量大于8的商品个数
        long count = goodsList.stream().filter(goods -> goods.getNum() > 8).count();
        System.out.println("count = " + count);
        // 7. max 返回流中最大值的元素, 按照一定的的规则,比如按照数量,先映射,要按照那个来进行作为比较的参照,然后使用compare
        Optional<Integer> optional = goodsList.stream().map(Goods::getNum).max(Integer::compare);
        System.out.println("optional.get() = " + optional.get());
        
        // 8. min 返回流中最小的元素
        Optional<Integer> min = goodsList.stream().map(Goods::getNum).min(Integer::compareTo);
        System.out.println("min.get() = " + min.get());
    }

输出结果:

allMatch = false
anyMatch = true
noneMatch = false
first.get() = Goods{id=1, goodsName='小米', num=12}
any.get() = Goods{id=3, goodsName='锤子科技', num=8}
count = 4
optional.get() = 15
min.get() = 8

8、Reduce归约–map做映射,归约求sum

Reduce(Integer indentity,BinaryOperator bi);
可以用来求出集合中 员工的总工资,购物车中的总价
传入两个参数,第一个是初始值,第二个是BiFunction<T, U, R>,传入两个值,返回一个值,两个值可以+ - * / 等操作,返回的值是他们的运算结果,Integer的sum 就满足这样的条件,当然这个函数也可以自定义

Integer的sum方法


 public static int sum(int a, int b) {
        return a + b;
    }

BiFunction 接口中的 R apply(T t, U u) 方法

@FunctionalInterface
public interface BiFunction<T, U, R> {
    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);

自己写的统计购物车中商品的数量:

  //reduce 归约
    @Test
    public void test9(){
        // 传入两个值,返回一个值(两个值相加,减法,乘法,/ , 等等运算),
        List<Goods> goodsList = new ShopCart().getGoodsList();
        Integer reduce = goodsList.stream().map(Goods::getNum).reduce(0, Integer::sum);
        System.out.println("reduce = " + reduce);
    }

输出结果

reduce = 55

9、收集 collect(collector c)

传入一个收集者,也就是将流收集到哪种类型的集合/容器当中,可以使用Collectors来定义

  • toList 就是list
  • toSet 就是set
  • toCollection 就是collection

在这里插入图片描述

代码:

 //collect 收集
    @Test
    public void test10(){
        //收集 商品数量>10的商品,并将他们存到新的集合中
        List<Goods> goodsList = new ShopCart().getGoodsList();
        //收集为list
        List<Goods> list = goodsList.stream().filter(goods -> goods.getNum() > 10).collect(Collectors.toList());
        System.out.println("list = " + list);
        //收集为set
        Set<Goods> goodsSet = goodsList.stream().filter(goods -> goods.getNum() > 10).collect(Collectors.toSet());
        System.out.println("goodsSet = " + goodsSet);
    }

输出结果

list = [Goods{id=1, goodsName='小米', num=12}, Goods{id=4, goodsName='荣耀8', num=15}]
goodsSet = [Goods{id=1, goodsName='小米', num=12}, Goods{id=4, goodsName='荣耀8', num=15}]

四、Optional 类

空指针异常是导致Java应用程序失败的最常见原因
Optional类可以更好的避免空指针异常;它是一个容器,可以装任意类型T的值,保存null表示这个值不存在

Optional中的方法:

1)创建Optional类对象的方法:

  • Optional.of(T t); 创建一个Optional实例,t必须为非空;
  • Optional.empty(); 创建一个空的Optional实例;
  • Optional.ofNullable(T t); t可以为空null

2)判断Optional容器中是否包含对象:

boolean isPresent(); 判断是否包含对象

3)获取容器中的对象

  • optional.orElse(T t); 返回一个对象,如果optional对象封装的t是空,那么返回orElse方法中的参数 备胎t,如果不是空,就返回optional中装的对象内部t;
  • get(); 获取元素 ,但是必须首先判断一下 isPresent,为true再get,否则会报空指针异常;

五、end 测试的完整类:

package com.xt.test;

import org.junit.jupiter.api.Test;

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

public class StreamTest {

    @Test
    public void testStream(){
        ShopCart shopCart = new ShopCart();
        List<Goods> goodsList = shopCart.getGoodsList();
        //创建stream,支持泛型,基本类型,数组
        //创建stream,串行的
        Stream<Goods> stream = goodsList.stream();

        // 创建并行的stream
        Stream<Goods> goodsStream = goodsList.parallelStream();

        //通过数组 Array
        Goods goods1 = new Goods(1001, "小米", 12);
        Goods goods2 = new Goods(1002, "华为", 5);
        Goods arr[]={goods1,goods2};
        Stream<Goods> stream1 = Arrays.stream(arr);

        // 通过 stream 的 of
        Stream<Integer> integerStream = Stream.of(1, 3, 5, 6, 7, 12);

    }
    // 无限流
    @Test
    public void test4(){
        // 输出 10个偶数,第一个supply,第二个是限制个数,第三个是 消费者打印出来结果,
        Stream.iterate(0,num -> num+2).limit(10).forEach(System.out::println);
    }
    //筛选与切片
    @Test
    public void test5(){
        ShopCart shopCart = new ShopCart();
        List<Goods> goodsList = shopCart.getGoodsList();
        Stream<Goods> stream = goodsList.stream();
        // 过滤,filter 接收lambda,返回boolean,从流中过滤某些元素,集合中商品goods库存num>10的
        stream.filter(goods -> goods.getNum()>10).forEach(System.out::println);

        System.out.println("************************************");
        // 截断流,不超过指定的数量
        goodsList.stream().limit(3).forEach(System.out::println);

        System.out.println("************************************");
        // 跳过 skip,
        goodsList.stream().skip(2).forEach(System.out::println);

        System.out.println("************************************");
        //筛选,需要重写hashcode和equals方法
        goodsList.add(new Goods(2,"华为",10));
        goodsList.add(new Goods(2,"华为",10));
        goodsList.add(new Goods(2,"华为",10));
        goodsList.stream().distinct().forEach(System.out::println);

    }

    @Test
    public void test6(){
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(String::toUpperCase).forEach(System.out::println);
        //获取商品名称大于3的 ,使用map映射 ,将商品对象映射为商品名称,  首先映射,然后
        List<Goods> goodsList = new ShopCart().getGoodsList();
        Stream<String> stringStream = goodsList.stream().map(Goods::getGoodsName).filter(str -> str.length() > 3);
        stringStream.forEach(System.out::println);

        // flatmap ,相当于list.addAll
        list.stream().flatMap(StreamTest::fromStringToStream).forEach(System.out::println);

    }


    // 将字符串 转换为字符的stream流
    public static Stream<Character> fromStringToStream(String str){
        char[] charArray = str.toCharArray();
        List<Character> list=new ArrayList();
        for (Character c:charArray
             ) {
            list.add(c);
        }
        return list.stream();

    }

    // sort排序
    @Test
    public void test7(){
        // 1. 基本数据类型的排序
        List<Integer> integerList = Arrays.asList(1, 4, 6, 3, 8, 2);
        integerList.stream().sorted().forEach(System.out::println);

        // 对象的排序,商品的数量排序 ,,在数量相同的情况下 id 倒序
        List<Goods> goodsList = new ShopCart().getGoodsList();
        goodsList.stream().sorted( (g1,g2) -> {
            int i = Integer.compare(g1.getNum(), g2.getNum());
            if (i!=0){
                return i;
            }
            return -Integer.compare(g1.getId(),g2.getId());

        } ).forEach(System.out::println);

    }

    // 匹配于查找
    @Test
    public void test8(){
        List<Goods> goodsList = new ShopCart().getGoodsList();
        // 1. allMatch  检查是否匹配所有元素,是否购物车 商品数量都大于 10
        boolean allMatch = goodsList.stream().allMatch(goods -> goods.getNum() > 10);
        System.out.println("allMatch = " + allMatch);

        // 2. anyMatch 检查至少匹配一个元素  数量>10的
        boolean anyMatch = goodsList.stream().anyMatch(goods -> goods.getNum() > 10);
        System.out.println("anyMatch = " + anyMatch);

        // 3. noneMatch 检查是否有不存在在 小 开头的商品,如果有存在以 ‘小’ 开头 或者其它条件,比如包含contains,以小 结尾  endWith
        boolean noneMatch = goodsList.stream().noneMatch(goods -> goods.getGoodsName().startsWith("小"));
        System.out.println("noneMatch = " + noneMatch);

        // 4. findFirst 查找第一个元素
        Optional<Goods> first = goodsList.stream().findFirst();
        System.out.println("first.get() = " + first.get());
        
        // 5. findAny 随机查找一个元素
        Optional<Goods> any = goodsList.parallelStream().findAny();
        System.out.println("any.get() = " + any.get());

        // 6. count 统计个数 ,可以先筛选,后统计; 统计数量大于8的商品个数
        long count = goodsList.stream().filter(goods -> goods.getNum() > 8).count();
        System.out.println("count = " + count);

        // 7. max 返回流中最大值的元素, 按照一定的的规则,比如按照数量,先映射,要按照那个来进行作为比较的参照,然后使用compare
        Optional<Integer> optional = goodsList.stream().map(Goods::getNum).max(Integer::compare);
        System.out.println("optional.get() = " + optional.get());
        
        // 8. min 返回流中最小的元素
        Optional<Integer> min = goodsList.stream().map(Goods::getNum).min(Integer::compareTo);
        System.out.println("min.get() = " + min.get());
    }

    //reduce 归约
    @Test
    public void test9(){
        // 传入两个值,返回一个值(两个值相加,减法,乘法,/ , 等等运算),
        List<Goods> goodsList = new ShopCart().getGoodsList();
        Integer reduce = goodsList.stream().map(Goods::getNum).reduce(0, Integer::sum);
        System.out.println("reduce = " + reduce);
    }

    //collect 收集
    @Test
    public void test10(){
        //收集 商品数量>10的商品,并将他们存到新的集合中
        List<Goods> goodsList = new ShopCart().getGoodsList();
        //收集为list
        List<Goods> list = goodsList.stream().filter(goods -> goods.getNum() > 10).collect(Collectors.toList());
        System.out.println("list = " + list);

        //收集为set
        Set<Goods> goodsSet = goodsList.stream().filter(goods -> goods.getNum() > 10).collect(Collectors.toSet());
        System.out.println("goodsSet = " + goodsSet);
    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值