lambda表达式和Stream

lambda

lambda表达式作用就是简化函数式接口匿名内部类代码的。

函数式接口:就是只有一个抽象方法的接口。

lambda是一种函数式编程。

函数式编程:就是将函数当做对象使用了,可以作为参数传递还可以作为返回值。

/**
 * 为什么使用Lambda?
 * 简单方便创建函数式接口对象,不需要写匿名内部类的方式
 */
public class App {
    public static void main(String[] args) {
        /**
         * 创建函数式接口对象:匿名内部类的方式
         */
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    System.out.println(i);
                }
            }
        };
        /**
         * Lambda方式创建函数式接口对象
         */
        Runnable runnable = () -> {
            for (int i = 0; i < 50; i++) {
                System.out.println(i);
            }
        };
        new Thread(runnable).start();
    }

lambda表达式的语法格式

()->{}
  • () 表示参数列表
    • 参数列表是函数式接口匿名内部类重写方法的参数列表
  • -> 表示lambda操作符,也可以叫做goes on
  • {} 表示lambda函数体
    • 函数体是函数式接口匿名内部类重写方法的方法体
package com.powernode.p3;

public class Demo01 {

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("java。。。。。。");
            }
        }).start();

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

        /**
         *  () 代表的就是run的参数列表
         *  System.out.println("java") 就是run方法的方法体
         *
         *  所以整个()-> System.out.println("java");就表示run()
         *
         *  所以lambda表达式就是一个函数。 lambda是函数式编程的,所以lambda表达式用函数表示了函数式接口的实现类对象
         *
         */
        new Thread(()-> System.out.println("java")).start();
    }
}

lambda表示函数,表示的是函数接口实现类重写的函数

lambda表示对象,表示的是函数接口实现类对象

lambda六大基础语法

/**
 * 多参数,无返回值
 */
public interface NoReturnMultiParam {
    void method(int a ,int b);
}

/**
 * 无参无返回值函数式接口
 */
public interface NoreturnNoParm {
    void method();
}

/**
 * 一个参数,无返回值
 */
public interface NoreturnOneParam {
    void method(int a);
}

/**
 * 多参数,有返回值
 */
public interface ReturnMultiParam {

    int method(int a,int b );
}

/**
 * 无参,有返回值
 */
public interface ReturnNoParam {
    int method();
}

/**
 * 一个参数,有返回值
 */
public interface ReturnOneParam {
    int method(int a );
}
package com.ws;

import com.ws.myinterface.*;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class LambaTest {

    @Test
    public void noParamNoReturn(){
        NoreturnNoParm noreturnNoParm = ()->{
            System.err.println("无参无返回值");
        };
        noreturnNoParm.method();
    }

    @Test
    public void OneParamNoReturn(){
        NoreturnOneParam noreturnOneParam = (b) -> {
            System.out.println("有一个参数,无返回值");
        };
      noreturnOneParam.method(4);
    }

    @Test
    public void multiParamNoReturn(){
        NoReturnMultiParam noReturnMultiParam = (a,b)->{
            System.out.println("多个参数,无返回值");
        };
        noReturnMultiParam.method(2,3);
    }

    @Test
    public void noParamReturn(){
        ReturnNoParam returnNoParam = ()->{
            System.out.println("无参,有返回值");
            return 3;
        };
        int method = returnNoParam.method();
        System.out.println(method);
    }

    @Test
    public void oneParamReturn(){
        ReturnOneParam returnOneParam = (a)->{
            System.out.println("有一个参数,有返回值");
            return a;
        };
        int method = returnOneParam.method(8);
        System.out.println(method);
    }


    @Test
    public void multiParamReturn(){
        ReturnMultiParam returnMultiParam = (a,b)->{
            System.out.println("有多个参数,有返回值");
            return a+b;
        };
        int method = returnMultiParam.method(3, 4);
        System.out.println(method);
    }


    @Test
    public void lsnf(){
        Thread thread = new Thread(()->{
            System.out.println("重写的Runnable接口的run方法");
        });
        thread.start();
    }
}

方法引用

lambda表达式是匿名内部类的简写,当某个函数式接口的方法,我们使用匿名内部类后发现,其它类的某个方法和我们写的匿名内部类一样的,我们就可以使用方法引用。 不过要求方法引用的返回值和参数必须和函数式接口的参数一样。

重点:必须要参数和返回值和接口的一样,才可以作为方法引用。

有4种:

1.静态方法引用:

​ 类名::方法名

package com.ws.myinterface.staticMethod;

/**
 * 测试静态方法引用,没有返回值类型
 */
@FunctionalInterface
public interface StaticeMethod {
    void sum(int a,int b);

}


package com.ws.myinterface.staticMethod;

/**
 * 测试静态方法引用,有返回值类型
 */
@FunctionalInterface
public interface StaticeMethod2 {
  int sum(int a,int b);

}



package com.ws.myinterface.staticMethod;

public class MyMethod {

  /**
   * 参数和函数式接口的一样,但是函数式接口没有返回值;
   * @param a
   * @param b
   * @return
   */
  public static int getSum(int a,int b){
    return a+b;
  }
  /**
   * 参数和返回值都和函数式接口的一样
   * @param a
   * @param b
   * @return
   */
  public static void getSum2(int a,int b){
    System.out.println(a+b);
  }

}

//证明过程
  
  /**
   * 静态方法引用:
   * 类名::静态方法名。
   * 结论:
   *  当函数式接口参数和静态方法参数相同,且函数式接口没有返回值的情况下:
   *      方法引用的的静态方法可以有返回值,也可以没有返回值。
   *  当说明函数式接口参数和静态方法参数相同,且函数式接口有返回值的情况下:
   *      方法引用的的静态方法必须有返回值.
   */
  @Test
  public void test1() {
    /**
     * 以下2行中,说明当函数式接口参数和静态方法参数相同,且函数式接口没有返回值的情况下,方法引用的的静态方法可以有返回值,也可以没有返回值。
     */
    StaticeMethod staticeMethod = MyMethod::getSum;
    StaticeMethod staticeMethod1 = MyMethod::getSum2;
    /**
     * 以下两行,说明函数式接口参数和静态方法参数相同,且函数式接口有返回值的情况下,方法引用的的静态方法必须有返回值.
     */
    StaticeMethod2 staticeMethod2 = MyMethod::getSum;
    //报错
//        StaticeMethod2 staticeMethod21 = MyMethod::getSum2;
  }
2.实例方法引用:

​ 实例名::方法名

​```java
package com.ws.myinterface.instanseMethod;
//测试实例方法引用
@FunctionalInterface
public interface InstanceMethod {
    void isEmpty(String str);
}
package com.ws.myinterface.instanseMethod;
//测试实例方法引用

@FunctionalInterface
public interface InstanceMethod2 {
  boolean isEmpty(String str);
}
package com.ws.myinterface.instanseMethod;

public class MethodForInstance {

  public void isEmpty(String str){
    boolean empty = str.isEmpty();
    System.out.println(empty);
  }

  public boolean sljf(String str){
    return str.isEmpty();
  }
}

//证明过程
  /**
   * 实例方法引用:
   * 对象::方法名
   * 结论:
   *      当函数式接口参数和实例方法参数相同,且函数式接口没有返回值的情况下:
   *          方法引用的的实例方法可以有返回值,也可以没有返回值;
   *      当函数式接口参数和实例方法参数相同,且函数式接口有返回值的情况下:
   *          方法引用的的实例方法必须有返回值.
   */
  @Test
  public void test2() {
    MethodForInstance methodForInstance = new MethodForInstance();
/**
 * 以下2行中,说明当函数式接口参数和实例方法参数相同,且函数式接口没有返回值的情况下,方法引用的的实例方法可以有返回值,也可以没有返回值。
 */
    InstanceMethod instanceMethod = methodForInstance::sljf;
    InstanceMethod instanceMethod1 = methodForInstance::isEmpty;
    /**
     * 以下两行,说明函数式接口参数和实例方法参数相同,且函数式接口有返回值的情况下,方法引用的的实例方法必须有返回值.
     */
    InstanceMethod2 instanceMethod2 = methodForInstance::sljf;
    //报错
//        InstanceMethod2 instanceMethod21 = methodForInstance::isEmpty;
  }

3.特殊方法引用:

​ (我们可以先写匿名内部类)如果匿名内部类的方法内容的返回值是参数调用某个方法(注意返回值不能存在运算),就可以使用特殊方法引用。

​ 格式:参数类::参数调用的方法名。

//测试特殊方法引用
@FunctionalInterface
public interface SpecialMethod {

  void isEmpty(MethodForSpecial str);
}
//测试特殊方法引用

@FunctionalInterface
public interface SpecialMethod2 {

  boolean isEmpty(MethodForSpecial str);
}
//测试特殊方法引用

@FunctionalInterface
public interface SpecialMethod3 {
  void isEmpty(MethodForSpecial str,String a,String b);
}
//测试特殊方法引用

@FunctionalInterface
public interface SpecialMethod4 {
  boolean isEmpty(MethodForSpecial str,String a,String b);
}
//测试特殊方法引用

@FunctionalInterface
public interface SpecialMethod5 {
  boolean isEmpty(String a,String b,MethodForSpecial str);
}

public class MethodForSpecial<T> {

  public void isEmpty() {
    System.out.println();
  }

  public boolean isContain() {
    return true;
  }

  public void noReturnThreeArgs(String a, String b) {

  }

  public boolean ReturnThreeArgs( String a, String b) {
    return true;
  }
}

//证明过程
  /**
   * 特殊方法引用:
   *  类名::实例方法名
   *  结论:
   *      1)函数式接口的参数必须比实例方法的参数多1个,并且是第1个参数。
   *      2)第1个参数必须是 实例方法所属类的类型或者父类的类型。
   */
  @Test
  public void test3() {
    SpecialMethod specialMethod = MethodForSpecial::isContain;
    SpecialMethod specialMethod1 = MethodForSpecial::isEmpty;


    SpecialMethod2 specialMethod2 = MethodForSpecial::isContain;
        /*报错
        SpecialMethod2 specialMethod21 = MethodForSpecial::isEmpty;*/


    SpecialMethod3 specialMethod3 = MethodForSpecial::noReturnThreeArgs;
    SpecialMethod3 specialMethod31 = MethodForSpecial::ReturnThreeArgs;


    SpecialMethod4 specialMethod4 = MethodForSpecial::ReturnThreeArgs;
        /*报错
        SpecialMethod4 specialMethod41 = MethodForSpecial::noReturnThreeArgs;*/


        /*两条都报错
        SpecialMethod5 specialMethod5 = MethodForSpecial::isContain;
        SpecialMethod5 specialMethod51 = MethodForSpecial::noReturnThreeArgs;*/
  }

4.构造方法引用:
//测试构造引用
public interface MyInterface {
  //抽象方法
  Integer strToInt(String str);
}
/**
     * 接口测试类 构造方法引用
     * 利用构造方法将String字符串转换成Integer类型
     *
     * 构造方法引用
     语法:类名::new
     注意事项:
     被引用的类必须存在一个构造方法与函数式接口的抽象方法参数列表一致
     */
    @Test
    public void test9(){
        // 采用匿名内部类的方式
        MyInterface my = new MyInterface() {

            @Override
            public Integer strToInt(String str) {
                // Integer integer = new
                // Integer(str);//创建一个构造方法将String类型转换成Integer类型(自动装箱)
                return new Integer(str); // 方法是一个构造方法
            }
        };

        // 采用lambda表达式对匿名内部类进行优化
        MyInterface my1 =  str ->  new Integer(str);

        // 采用构造方法引用进行简化代码
        MyInterface my2 =  Integer::new;

        // 调用方法输出结果
        System.out.println(my.strToInt("232434"));
        System.out.println(my1.strToInt("232434"));
        System.out.println(my2.strToInt("232434"));
    }

Stream:

Stream 表示数据流,是jdk8的新特性。Stream可以简化集合/数组的操作。

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

package com.ws;

import com.ws.stream.People;
import com.ws.stream.Student;
import com.ws.stream.User;
import org.junit.Test;

import java.io.PrintStream;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Stream:
 *      1.filter:筛选
 *      2.anyMatch:匹配任意一个
 *      3.allMatch:匹配所有
 *      4.sorted:使用Comparator.comparing来进行排序。
 *            a.正序
 *            b.反序
 *            c.先按xx排序,再按yy排序
 *      5.skip:跳过几个元素
 *      6.distinct:对集合去重
 *      7.map: 统一对集合中满足条件的元素做某操作。
 *      8.collect:
 *          a.转换为其它集合
 *              1.转换为map:注意转换后key必须保持唯一。
 *              2.转换为concurrentMap:注意转换后key必须保持唯一
 *              3.转换为List
 *              4.转换为set
 *          b.分组/分区
 *              1.Collectors.groupingBy:
 *                 a.根据集合元素的某属性进行分组,返回的map key为属性值
 *                   b.根据某种条件来进行分组,返回的map  key 为 boolean值。
 *              2.Collectors.partitioningBy
 *                  这个方法是分区方法,key只能是boolean类型,用groupingBy可以实现。
 *          c.聚合运算
 *              a.获取某元素的总和:summing
 *              b.获取平均数 :averaging
 *              c.获取max和min
 *              d.获取符合条件的数量:count
 *
 *
 */
public class StreamTest {
    /**
     * foreach
     */
    @Test
    public void test() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //1. 顺序遍历
        list.stream().forEach(System.out::println);
    }

    /**
     * filter:筛选,筛选出集合中满足条件的元素
     */
    @Test
    public void test1() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //1.筛选出集合中>5的元素并且输出
        list.stream().filter(a -> a > 5).forEach(System.out::println);
        //2.筛选出集合中>5且<9的元素且输出
        list.stream().filter(a -> a > 5 && a < 9).forEach(System.out::println);
    }

    /**
     * anyMatch:判断集合中是否存在满足条件的元素,返回Boolean类型
     */
    @Test
    public void test2() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //1.判断集合中是否有>8的元素
        boolean b = list.stream().anyMatch(a -> a > 8);

    }

    /**
     * allMatch: 判断集合的所有元素是否都满足某个条件,返回boolean类型
     */
    @Test
    public void test3() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //集合中的所有元素是否都 >0和<10?
        boolean b = list.stream().allMatch(a -> a > 0 && a < 10);
        System.out.println(b);
    }

    /**
     * sorted:排序:使用Comparator.comparing来进行排序。
     *      a.正序
     *      b.反序
     *      c.先按xx排序,再按yy排序
     */
    @Test
    public void test4() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        List<User> users = Arrays.asList(new User(1, "亚索", "巨神峰", 20, 99, new Date(), Arrays.asList("吹风", "吹笛子", "睡觉")), new User(2, "德玛", "德玛西亚", 21, 95, new Date(), Arrays.asList("大保健", "冲锋", "睡觉")), new User(3, "光辉", "德玛西亚", 22, 80, new Date(), Arrays.asList("魔法棒", "激光", "睡觉")), new User(4, "发条", "黑色玫瑰", 23, 75, new Date(), Arrays.asList("玩球", "上发条")), new User(5, "铁男", "黑色玫瑰", 24, 75, new Date(), Arrays.asList("棒子", "小黑屋", "睡觉")), new User(6, "提莫", "巨神峰", 25, 70, new Date(), Arrays.asList("种蘑菇", "采蘑菇", "吹笛子")), new User(7, "卢锡安", "巨神峰", 26, 60, new Date(), Arrays.asList("双枪", "滑步")), new User(8, "卡牌大师", "诺克萨斯", 27, 65, new Date(), Arrays.asList("玩牌", "黄牌")), new User(9, "雷克顿", "德玛西亚", 28, 60, new Date(), Arrays.asList("飞顿", "睡觉")));

        //将集合按从小到大排序并转换为新的集合,并反序排序
        list.stream().sorted().collect(Collectors.toList()).forEach(System.out::println);
        List<Integer> collect3 = list.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());
        List<Integer> collect4 = list.stream().sorted(Comparator.comparing(Integer::intValue).reversed()).collect(Collectors.toList());
        //将集合按从大到小的顺序排序,反序排序
        List<User> collect = users.stream().sorted(Comparator.comparing(User::getScore)).collect(Collectors.toList());
        List<User> collect1 = users.stream().sorted(Comparator.comparing(User::getScore).reversed()).collect(Collectors.toList());

        //先按年龄排序,再按分数排序
        List<User> collect2 = users.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getScore)).collect(Collectors.toList());

    }

    /**
     * max:获取集合的最大值
     */
    @Test
    public void test5() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        Integer integer = list.stream().max(Integer::compare).get();
        System.out.println(integer);
    }

    /**
     * min:获取集合元素的最小值。
     */
    @Test
    public void test6() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        Integer integer = list.stream().min(Integer::compareTo).get();
        System.out.println(integer);
    }

    /**
     * skip:跳过几个元素
     */
    @Test
    public void test7() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        list.stream().skip(3).forEach(System.out::println);
    }

    /**
     * distinct():给集合去重
     */
    @Test
    public void test8() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1, 9);
        //1. 将list集合去重
        list = list.stream().distinct().collect(Collectors.toList());
        list.forEach(System.err::println);
    }

    /**
     * map:将集合中满足条件的统一做 某种操作;获取将所有元素做某种操作
     */
    @Test
    public void test9() {
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
        //将集合中>5的元素+5
        list.stream().map(a -> {
            if (a > 5) {
                return a + 10;
            }
            return a;
        }).collect(Collectors.toList()).forEach(System.out::println);

    }


    /**
     * 重点collect()系列:
     */


    /**
     * 1.collect()之转换集合
     * a.转换为map集合:自己选择用集合元素的什么属性来做key和value。
     * 注意设置key的时候,key应该是唯一的,不然会报错.
     * b.转换为List集合
     * c.转换为set集合,可以完成list集合的去重功能
     * d.转换为concurrentMap
     * 注意设置key的时候,key应该是唯一的,不然会报错.
     */
    @Test
    public void test10() {
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1, 2);
        //将元素中>5的元素转换为一个新的集合
        List<Integer> list1 = list.stream().filter(a -> a > 5).collect(Collectors.toList());
        //转换为set集合,完成去重功能
        Set<Integer> set = list.stream().collect(Collectors.toSet());

        /**
         * 转换为map集合:
         *  a.如果自定义的有重复值,它就会抛出异常;只能使用下面那个方法,来指定key重复选择的策略。
         */
//        Map<Integer, String> map = list.stream().collect(Collectors.toMap(Integer::intValue, String::valueOf));//重复会报错
        Map<Integer, String> map2 = list.stream().collect(Collectors.toMap(Integer::intValue, String::valueOf, (k, v) -> v));


        /**
         * 转换为concurrentMap集合:
         *  a.如果自定义的有重复值,它就会抛出异常;只能使用下面那个方法,来指定key重复选择的策略。
         */
//        ConcurrentMap<Integer, String> concurrentMap = list.stream().collect(Collectors.toConcurrentMap(Integer::intValue, String::valueOf));//重复会报错
        ConcurrentMap<Integer, String> concurrentMap2 = list.stream().collect(Collectors.toConcurrentMap(Integer::intValue, String::valueOf, (k, v) -> v));


        People zs = new People(1, "张三");
        People ls = new People(2, "李四");
        People ww = new People(3, "王五");
        People ll = new People(4, "王五");
        ArrayList<People> people = new ArrayList<>();
        people.add(zs);
        people.add(ls);
        people.add(ww);
        people.add(ll);
        //Function.identity():指的是元素里面的当前元素,可以换为:p->p
        Map<Integer, People> collect = people.stream().
                collect(Collectors.toMap(People::getId, Function.identity()));
    }


    /**
     *  2.分组、分区处理。
     *   a.根据集合元素的某属性进行分组,返回的map key为属性值
     *   b.根据某种条件来进行分组,返回的map  key 为 boolean值。
     */
    @Test
    public void test11() {
        People zs = new People(1, "张三");
        People ls = new People(2, "李四");
        People ww = new People(3, "王五");
        People ll = new People(4, "王五");
        ArrayList<People> people = new ArrayList<>();
        people.add(zs);
        people.add(ls);
        people.add(ww);
        people.add(ll);

        //根据人的姓名分组,返回Map,key为人分组后的姓名,value集合元素
        Map<String, List<People>> collect = people.stream().collect(Collectors.groupingBy(People::getName));
        System.out.println(collect.toString());

        //根据人的姓名分组,返回concurrentMap
        ConcurrentMap<String, List<People>> collect1 = people.stream().collect(Collectors.groupingByConcurrent(People::getName));
        System.out.println(collect1.toString());

        //根据id按奇偶数进行分组,返回map,key为boolean类型
        Map<Boolean, List<People>> collect2 = people.stream().collect(Collectors.groupingBy(a -> a.getId() % 2 == 0));
        System.out.println(collect2.toString());

        //这个方法是分区方法,key只能是boolean类型,用groupingBy可以实现。
        Map<Boolean, List<People>> collect3 = people.stream().collect(Collectors.partitioningBy(a -> a.getId() % 2 == 0));
        System.out.println(collect3.toString());

    }


    /**
     * 3.聚合 处理:
     *      a.获取某元素的总和:summing
     *      b.获取平均数 :averaging
     *      c.获取max和min
     *      d.获取符合条件的数量:count
     */
    @Test
    public void test12() {
        Student ysSuo = new Student(1, "压缩", 12);
        Student jie = new Student(2, "劫", 88);
        Student saiLaSi = new Student(3, "塞拉斯", 98);
        Student xiaZi = new Student(4, "盲僧", 48);
        ArrayList<Student> lis = new ArrayList<>();
        lis.add(ysSuo);lis.add(jie);lis.add(saiLaSi);lis.add(xiaZi);
        //获取学生成绩总和
        Double collect = lis.stream().
                collect(Collectors.summingDouble(Student::getScore));

        //获取平均成绩
        Double averaging = lis.stream().
                collect(Collectors.averagingDouble(Student::getScore));

        //获取分数最高的学生姓名
        Double aDouble = lis.stream().
                map(Student::getScore).
                collect(Collectors.maxBy(Double::compareTo)).
                get();
        List<String> nameList = lis.stream()
                .filter(ins -> ins.getScore() == aDouble)
                .map(Student::getName)
                .collect(Collectors.toList());
        System.out.println(nameList);

        //获取最小分数
        Double min = lis.stream()
                .map(Student::getScore)
                .collect(Collectors.minBy(Double::compareTo))
                .get();

        //获取及格的学生人生
        Long collect1 = lis.stream()
                .filter(ins -> ins.getScore() > 60)
                .collect(Collectors.counting());
        System.out.println(collect);
        System.out.println(averaging);
        System.out.println(aDouble);
        System.out.println(min);
        System.out.println(collect1);

    }
}






//collect系列:
package com.ws;
 
import org.junit.Test;
import org.springframework.boot.test.context.SpringBootTest;
 
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.stream.Collectors;
 
 
/*
    stream.collect(x) 系列:
        1.收集为集合:
            收集为map,list.set.Connection下面的具体集合
        2.聚合函数  :max/min/sum/count/avg
            Collectors.summarizingInt:包含了5个集合函数,不用再多写代码。
        3.join
            只能用于集合数据元素为String类型的,如果不是数据类型,需要将其转换为String后再操作
        4.Collectors.mapping():
            和map的用法差不多。但是如果在collect中,就使用mapping方式,如果不是,可以使用map方式。
        5.Collectors.groupingBy()
            分组。
 **/
@SpringBootTest
public class StreamTest {
 
    /*
        1.收集为集合:
            collect(Collectors.toList()):转换为List集合
            collect(Collectors.toSet()):转换为set集合
            Collectors.toMap(a -> a, b -> b):转换为map集合
            Collectors.toConcurrentMap(Function.identity(), Function.identity())
            collect(Collectors.toCollection(ArrayList::new)):转化为Collection下面的具体集合
     **/
    @Test
    public void testOther() {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
 
        //收集为List/set/map/concurrenmap
        List<String> collect4 = list.stream().collect(Collectors.toList());
        Set<String> collect5 = list.stream().collect(Collectors.toSet());
        Map<String, String> collect6 = list.stream().collect(Collectors.toMap(a -> a, b -> b));
        ConcurrentMap<String, String> collect7 = list.stream().collect(Collectors.toConcurrentMap(Function.identity(), Function.identity()));
 
        //收集为Connection下面的具体集合
        ArrayList<String> collect = list.stream().collect(Collectors.toCollection(ArrayList::new));
        Vector<String> collect1 = list.stream().collect(Collectors.toCollection(Vector::new));
        LinkedList<String> collect2 = list.stream().collect(Collectors.toCollection(LinkedList::new));
        HashSet<String> collect3 = list.stream().collect(Collectors.toCollection(HashSet::new));
    }
 
    /*
        2.聚合函数:
            max()/min/sum/count/avg:  每个例子都只能获取1个值,如果都想获取,那么要写5个吗?使用下面这种方式
      重点:      Collectors.summarizingInt(Integer::intValue): 返回IntSummaryStatistics对象,但是里面已经全封装了,直接取就行。
     **/
    @Test
    public void testJuHe() {
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(3);
        integers.add(4);
        integers.add(5);
        integers.add(7);
 
        Integer integer = integers.stream().collect(Collectors.maxBy(Integer::compareTo)).get();
        Integer integer1 = integers.stream().collect(Collectors.minBy(Integer::compareTo)).get();
        Double collect = integers.stream().collect(Collectors.averagingInt(Integer::intValue));
        Long collect1 = integers.stream().collect(Collectors.counting());
        long count = integers.stream().collect(Collectors.summingInt(Integer::intValue));
 
        IntSummaryStatistics collect2 = integers.stream().collect(Collectors.summarizingInt(Integer::intValue));
        int max = collect2.getMax();
        int min = collect2.getMin();
        double average = collect2.getAverage();
        long count1 = collect2.getCount();
        long sum = collect2.getSum();
 
        System.out.println(integer==max);
        System.out.println(min==integer1);
        System.out.println(average==collect);
        System.out.println(count1==collect1);
        System.out.println(sum==count);
 
    }
 
    /**
     *    3. join:只能用于集合数据元素为String类型的,如果不是数据类型,需要将其转换为String后再操作
     *     collect(Collectors.joining()):
     *      collect(Collectors.joining(",")):
     *      collect(Collectors.joining(",", "[", "]")):
     **/
    @Test
    public void testJoining() {
        //当集合数据类型为String时
        List<String> strings = Arrays.asList("1", "4", "8", "9");
        String collect = strings.stream().collect(Collectors.joining());
        String collect1 = strings.stream().collect(Collectors.joining(","));
        String collect3 = strings.stream().collect(Collectors.joining(",", "[", "]"));
        System.out.println(collect);
        System.out.println(collect1);
        System.out.println(collect3);
 
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(3);
        integers.add(4);
        integers.add(5);
        integers.add(7);
        //当集合数据类型不为String时
        String collect2 = integers.stream().map(a -> a.toString()).collect(Collectors.joining(","));
        System.out.println(collect2);
 
    }
 
 
    /*
        4.
        Collectors.mapping():和map的用法差不多。但是如果在collect中,就使用mapping方式,如果不是,可以使用map方式。
        collect(Collectors.mapping(a -> a + 4, Collectors.toList())):
     **/
    @Test
    public void testMapping() {
 
        List<String> strings = Arrays.asList("1", "4", "8", "9");
        List<String> collect = strings.stream().collect(Collectors.mapping(a -> a + 4, Collectors.toList()));
        System.out.println(collect);
 
        List<String> collect1 = strings.stream().map(a -> a + 4).collect(Collectors.toList());
        System.out.println(collect1);
 
    }
 
    /*
        5.分组
                Collectors.groupingBy
     **/
    @Test
    public void testGroupingBy() {
 
        List<Integer> strings = Arrays.asList(1, 3, 4, 6,1,1,3);
        Map<Integer, List<Integer>> collect = strings.stream().collect(Collectors.groupingBy(Integer::intValue));
        //上面的写法等价于下面的写法
        Map<Integer, List<Integer>> collect1 = strings.stream().collect(Collectors.groupingBy(Integer::intValue, Collectors.toList()));
        //如果分组后的value不想用list,可以用其它集合
        Map<Integer, Set<Integer>> collect2 = strings.stream().collect(Collectors.groupingBy(Integer::intValue, Collectors.toSet()));
        System.out.println(collect);
    }
}

对应的实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {
    private int id;
    private String name;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private int id;
    private String name;
    private double score;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String addr;
    private Integer age;
    private Integer score;
    private Date birth;
    private List<String> hobby;

}

练习:

package com.ws;

import com.ws.stream.User;
import org.junit.Before;
import org.junit.Test;


import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class StreamHomeword {
    private List<User> users;

    @Before
    public void test() {
        users = Arrays.asList(new User(1, "亚索", "巨神峰", 20, 99, new Date(), Arrays.asList("吹风", "吹笛子", "睡觉")),
                new User(2, "德玛", "德玛西亚", 21, 95, new Date(), Arrays.asList("大保健", "冲锋", "睡觉")),
                new User(3, "光辉", "德玛西亚", 22, 80, new Date(), Arrays.asList("魔法棒", "激光", "睡觉")),
                new User(4, "发条", "黑色玫瑰", 23, 75, new Date(), Arrays.asList("玩球", "上发条")),
                new User(5, "铁男", "黑色玫瑰", 24, 75, new Date(), Arrays.asList("棒子", "小黑屋", "睡觉")),
                new User(6, "提莫", "巨神峰", 25, 70, new Date(), Arrays.asList("种蘑菇", "采蘑菇", "吹笛子")),
                new User(7, "卢锡安", "巨神峰", 26, 60, new Date(), Arrays.asList("双枪", "滑步")),
                new User(8, "卡牌大师", "诺克萨斯", 27, 65, new Date(), Arrays.asList("玩牌", "黄牌")),
                new User(9, "雷克顿", "德玛西亚", 28, 60, new Date(), Arrays.asList("飞顿", "睡觉")));
    }

    /*    1.拿到所有用户的名字集合
    2.拿到年龄小于25的人的名字集合
    3.根据分数倒排序
    4.拿到爱好里面有睡觉的 集合
    5.拿到来自德玛西亚的用户,根据分数排序,取前两个的名字
    6.计算分数总和*/
    @Test
    public void test1() {
        List<String> collect = users.stream().map(User::getName).collect(Collectors.toList());

        List<String> collect1 = users.stream().filter(a -> a.getAge() < 25).map(User::getName).collect(Collectors.toList());

        List<User> collect2 = users.stream().sorted(Comparator.comparing(User::getScore).reversed()).collect(Collectors.toList());

        List<User> sleep = users.stream().filter(s -> s.getHobby().contains("睡觉")).collect(Collectors.toList());

        List<User> deMa = users.stream().filter(a -> a.getAddr().equals("德玛西亚")).sorted(Comparator.comparing(User::getScore)).limit(2).collect(Collectors.toList());

        Integer collect3 = users.stream().collect(Collectors.summingInt(User::getScore));

        System.out.println(collect);
        System.out.println(collect1);
        System.out.println(collect2);
        System.out.println(sleep);
        System.out.println(deMa);
        System.out.println(collect3);

    }
}

到所有用户的名字集合
2.拿到年龄小于25的人的名字集合
3.根据分数倒排序
4.拿到爱好里面有睡觉的 集合
5.拿到来自德玛西亚的用户,根据分数排序,取前两个的名字
6.计算分数总和*/
@Test
public void test1() {
List collect = users.stream().map(User::getName).collect(Collectors.toList());

    List<String> collect1 = users.stream().filter(a -> a.getAge() < 25).map(User::getName).collect(Collectors.toList());

    List<User> collect2 = users.stream().sorted(Comparator.comparing(User::getScore).reversed()).collect(Collectors.toList());

    List<User> sleep = users.stream().filter(s -> s.getHobby().contains("睡觉")).collect(Collectors.toList());

    List<User> deMa = users.stream().filter(a -> a.getAddr().equals("德玛西亚")).sorted(Comparator.comparing(User::getScore)).limit(2).collect(Collectors.toList());

    Integer collect3 = users.stream().collect(Collectors.summingInt(User::getScore));

    System.out.println(collect);
    System.out.println(collect1);
    System.out.println(collect2);
    System.out.println(sleep);
    System.out.println(deMa);
    System.out.println(collect3);

}

}











  • 24
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值