• lambda之美


    github源码

    大前提:jdk8  允许lambda表达式  最好在maven中加入

    <properties>
    <java.version>1.8</java.version>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    只总结真香案例!!!

    案例一:

    从"1" "2" "bilibili" "of" "codesheep" "5" "codesheep" "5" "at" "BILIBILI" "codesheep" "23" "CHEERS" "6"中
    找出所有 长度>=5的字符串,并且忽略大小写、去除重复字符串,然后按字母排序,最后用“ * ”连接成一个字符串输出
    List<String> list = new ArrayList<>();
    list.add("1");
    ···
    list,add("6");
    String str = list.stream()//list转为stream流
    .filter(i -> !isNum(i))//过滤出不是数字的 也就是 得到字符 isNum是自己封装的方法
    .filter(i -> i.length()>5)//过滤出长度大于5的
    .map(i -> i.toLowerCase())//转为小写
    .distinct()//去重
    .sorted(Comparator.naturalOrder())//字符串排序
    .collect(Collectors.joining("*"));//字符串连接
    System.out.println(str);

    案例二:

    public class Lambda2 {
    public static void main(String[] args) {
    /**
    * 函数接口:Predict
    * 抽象方法:test(T t)
    * 参数:T
    * 返回值类型:Boolean
    * 功能:判断真假
    * 示例:判断学生身高
    * 结果:韩非的身高高于185吗?: false
    */
    Predicate<Integer> predicate = x -> x > 185;
    Student student = new Student("韩非", 23, 175);
    System.out.println("韩非的身高高于185吗?: " + predicate.test(student.getLength()));

    /**
    * 函数接口:Consumer
    * 抽象方法:accept(T t)
    * 参数:T
    * 返回值类型:void
    * 功能:消费消息
    * 示例:输出值
    * 结果:列东方位 青龙
    */
    Consumer<String> consumer = System.out::println;
    consumer.accept("列东方位 青龙");

    /**
    * 函数接口:Function
    * 抽象方法:R apply(T t)
    * 参数:T
    * 返回值类型:R
    * 功能:将T映射为R(转换功能)
    * 示例:输出student名字
    * 结果:韩非
    *
    * 备注:Student::getName这种lambda表达式写法被称为 方法引用 格式为 ClassName::MethodName
    */
    Function<Student, String> function = Student::getName;
    String name = function.apply(student);
    System.out.println(name);

    /**
    * 函数接口:Supplier
    * 抽象方法:T get()
    * 参数:void
    * 返回值类型:T
    * 功能:生产消息
    * 示例:工厂方法
    * 结果:10
    */
    Supplier<Integer> supplier = () -> Integer.valueOf(BigDecimal.TEN.toString());
    System.out.println(supplier.get());

    /**
    * 函数接口:UnaryOperator
    * 抽象方法:T apply(T t)
    * 参数:T
    * 返回值类型:T
    * 功能:一元操作
    * 示例:逻辑非(!)
    * 结果:false
    */
    UnaryOperator<Boolean> unaryOperator = uglily -> !uglily;
    Boolean apply2 = unaryOperator.apply(true);
    System.out.println(apply2);
    //使用BinaryOperator函数式接口 抽象方法T apply(T t, U u) 功能:二元操作 参数T,U 返回值类型T 求两个数乘积

    /**
    * 函数接口:BinaryOperator
    * 抽象方法:T apply(T t, U u)
    * 参数:T,U
    * 返回值类型:T
    * 功能:二元操作
    * 示例:求两个数乘积
    * 结果: 6
    */
    BinaryOperator<Integer> operator = (x, y) -> x * y;
    Integer integer = operator.apply(2, 3);
    System.out.println(integer);

    /**
    * 演示函数式接口
    * 结果:我是一个演示的函数式接口
    */
    test(() -> "我是一个演示的函数式接口");
    }
    /**
    * 演示自定义函数式接口使用
    *
    * @param worker
    */
    public static void test(Worker worker) {
    String work = worker.work();
    System.out.println(work);
    }
    public interface Worker {
    String work();
    }
    }

    案例三:

    /**
    * 惰性求值:只描述Stream,操作的结果也是Stream,这样的操作称为惰性求值。惰性求值可以像建造者模式一样链式使用,最后再使用及早求值得到最终结果。
    * 及早求值:得到最终的结果而不是Stream,这样的操作称为及早求值。
    *
    * 常用的流:collect(Collectors.toList())
    * 功能:将流转为list
    * 结果:[Student(name=路飞, age=22, length=175, specialisies=null), Student(name=红发, age=40, length=180, specialisies=null)]
    */
    List<Student> studentList = Stream.of(
    new Student("路飞", 22, 175),
    new Student("红发", 40, 180)
    ).collect(Collectors.toList());
    System.out.println(studentList);

    案例四:

    /**
    * 常用的流:filter
    * 功能:顾名思义,起过滤筛选的作用。内部就是Predicate接口。惰性求值。
    * 示例:筛选出身高小于180的同学
    * 结果:[Student(name=路飞, age=22, length=175, specialisies=null)]
    */
    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));
    List<Student> list = students.stream()
    .filter(stu -> stu.getLength() < 180)
    .collect(Collectors.toList());
    System.out.println(list);

    案例五:

    /**
    * 常用的流:map
    * 功能:转换功能,内部就是Function接口。惰性求值
    * 示例:获取所有同学的名字
    * 结果:[路飞, 红发, 白胡子]
    */
    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));
    List<String> names = students.stream().map(student -> student.getName())
    .collect(Collectors.toList());
    System.out.println(names);

    案例六:

    /**
    * 常用的流:flatMap
    * 功能:将多个Stream合并为一个Stream。惰性求值
    * 示例:调用Stream.of的静态方法将两个list转换为Stream,再通过flatMap将两个流合并为一个
    * 结果:[
    * Student(name=路飞, age=22, length=175, specialisies=null),
    * Student(name=红发, age=40, length=180, specialisies=null),
    * Student(name=白胡子, age=50, length=185, specialisies=null),
    * Student(name=艾斯, age=25, length=183, specialisies=null),
    * Student(name=雷利, age=48, length=176, specialisies=null)
    * ]
    */
    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));
    List<Student> studentList = Stream.of(students,
    Arrays.asList(new Student("艾斯", 25, 183),
    new Student("雷利", 48, 176)))
    .flatMap(students1 -> students1.stream()).collect(Collectors.toList());
    System.out.println(studentList);

    案例七:

    /**
    * 常用的流:max min
    * 功能:我们经常会在集合中求最大或最小值,使用流就很方便。及早求值。
    * 示例:得到年龄最大和最小的同学
    * 结果:Student(name=白胡子, age=50, length=185, specialisies=null)
    * Student(name=路飞, age=22, length=175, specialisies=null)
    *
    * 补充:max、min接收一个Comparator(例子中使用java8自带的静态函数,只需要传进需要比较值即可。)
    * 并且返回一个Optional对象,该对象是java8新增的类,专门为了防止null引发的空指针异常。可以使用max.isPresent()判断是否有值;
    * 可以使用max.orElse(new Student()),当值为null时就使用给定值;也可以使用max.orElseGet(() -> new Student());
    * 这需要传入一个Supplier的lambda表达式。
    */
    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));
    Optional<Student> max = students.stream()
    .max(Comparator.comparing(stu -> stu.getAge()));
    Optional<Student> min = students.stream()
    .min(Comparator.comparing(stu -> stu.getAge()));
    //判断是否有值
    if (max.isPresent()) {
    System.out.println(max.get());
    }
    if (min.isPresent()) {
    System.out.println(min.get());
    }

    案例八:

    /**
    * 常用的流:count
    * 功能:统计功能,一般都是结合filter使用,因为先筛选出我们需要的再统计即可。及早求值
    * 示例:统计年龄小于45的人数
    * 结果:年龄小于45岁的人数是:2
    */
    public static void main(String[] args) {
    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));
    long count = students.stream().filter(s1 -> s1.getAge() < 45).count();
    System.out.println("年龄小于45岁的人数是:" + count);
    }

    案例九:

    /**
    * 常用的流:reduce
    * 功能:reduce 操作可以实现从一组值中生成一个值。前面案例用到的 count 、 min 和 max 方法,因为常用而被纳入标准库中。事实上,这些方法都是 reduce 操作。及早求值。
    * 示例:reduce接收了一个初始值为0的累加器,依次取出值与累加器相加,最后累加器的值就是最终的结果
    * 结果:10
    */
    public static void main(String[] args) {
    Integer reduce = Stream.of(1, 2, 3, 4).reduce(0, (acc, x) -> acc+ x);
    System.out.println(reduce);
    }

    案例十:

     /**
    * 收集器,一种通用的、从流生成复杂值的结构。只要将它传给 collect 方法,所有
    * 的流就都可以使用它了。标准类库已经提供了一些有用的收集器,以下示例代码中的收集器都是从 java.util.stream.Collectors 类中静态导入的。
    *
    *
    * 结果:人数最多的班级是:一班 一班平均年龄是:37.666666666666664
    */
    public static void main(String[] args) {
    List<Student> students1 = new ArrayList<>(3);
    students1.add(new Student("路飞", 23, 175));
    students1.add(new Student("红发", 40, 180));
    students1.add(new Student("白胡子", 50, 185));
    OutstandingClass ostClass1 = new OutstandingClass("一班", students1);
    //复制students1,并移除一个学生
    List<Student> students2 = new ArrayList<>(students1);
    students2.remove(1);
    OutstandingClass ostClass2 = new OutstandingClass("二班", students2);
    //将ostClass1、ostClass2转换为Stream
    Stream<OutstandingClass> classStream = Stream.of(ostClass1, ostClass2);
    OutstandingClass outstandingClass = biggestGroup(classStream);
    System.out.println("人数最多的班级是:" + outstandingClass.getName());
    System.out.println("一班平均年龄是:" + averageNumberOfStudent(students1));
    }

    /**
    * 获取人数最多的班级
    * 无论选择哪种返回值语句都可以
    * 区别是 Optional中对null做了许多封装,可以进行空值的校验
    * orElseGet方法 如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值
    */
    private static OutstandingClass biggestGroup(Stream<OutstandingClass> outstandingClasses) {
    // return outstandingClasses.max(Comparator.comparing(stu -> stu.getStudents().size())).get();
    return Optional.of(outstandingClasses.max(Comparator.comparing(stu -> stu.getStudents().size())).get()).orElseGet(OutstandingClass:: new );
    }
    /**
    * 计算平均年龄
    */
    private static double averageNumberOfStudent(List<Student> students) {
    return students.stream().collect(Collectors.averagingInt(Student::getAge));
    }

     案例十一:

    /**
    * 常用的流:Predicate
    * 功能:将流分解成两个集合,接收一个Predicate函数式接口。
    * 示例:按照会sing的和不会sing对学生进行分拆
    * 结果:{
    * false=[Student(name=红发, age=40, length=180, specialisies=swimming), Student(name=白胡子, age=50, length=185, specialisies=dance)],
    * true=[Student(name=路飞, age=23, length=175, specialisies=sing)]
    * }
    * 和Collectors.groupingBy() 分组类似
    */
    List<Student> students = new ArrayList<>(3);
    Student stu1 = new Student("路飞", 23, 175);
    stu1.setSpecialisies("sing");
    students.add(stu1);
    Student stu2 = new Student("红发", 40, 180);
    stu2.setSpecialisies("swimming");
    students.add(stu2);
    Student stu3 = new Student("白胡子", 50, 185);
    stu3.setSpecialisies("dance");
    students.add(stu3);
    Map<Boolean, List<Student>> listMap = students.stream().collect(
    Collectors.partitioningBy(stu ->
    stu.getSpecialisies().
    contains(SpecialityEnum.SING.name)));
    System.out.println(listMap);

    //使用Collectors.groupingBy()也可完成同样的功能
    Map<Boolean, List<Student>> li = students.stream().collect(Collectors.groupingBy(student -> student.getSpecialisies().contains(SpecialityEnum.SING.name)));
    System.out.println(li);

    案例十二:

    /**
    * 常用的流:数据分组groupingBy 分组条件通常会被作为Map的key
    * 功能:数据分组是一种更自然的分割数据操作,与将数据分成 ture 和 false 两部分不同,可以使用任意值对数据分组。Collectors.groupingBy接收一个Function做转换。
    * 示例:按照会特长对学生进行分组
    * 结果:{
    * swimming=[Student(name=红发, age=40, length=180, specialisies=swimming)],
    * sing=[Student(name=路飞, age=23, length=175, specialisies=sing)],
    * dance=[Student(name=白胡子, age=50, length=185, specialisies=dance)]
    * }
    * 分组条件可以拼接多个 但是要和声明的类型(Map的key)一致
    * 示例:声明类型是String
    * 分组条件:特长***名字 stu.getSpecialisies()+"***"+stu.getName()
    * 结果:{
    * dance***白胡子=[Student(name=白胡子, age=50, length=185, specialisies=dance)],
    * sing***路飞=[Student(name=路飞, age=23, length=175, specialisies=sing)],
    * swimming***红发=[Student(name=红发, age=40, length=180, specialisies=swimming)]
    * }
    */
    List<Student> students = new ArrayList<>(3);
    Student stu1 = new Student("路飞", 23, 175);
    stu1.setSpecialisies("sing");
    students.add(stu1);
    Student stu2 = new Student("红发", 40, 180);
    stu2.setSpecialisies("swimming");
    students.add(stu2);
    Student stu3 = new Student("白胡子", 50, 185);
    stu3.setSpecialisies("dance");
    students.add(stu3);
    Map<String, List<Student>> listMap =
    students.stream().collect(
    Collectors.groupingBy(stu -> stu.getSpecialisies()));
    System.out.println(listMap);
    Map<String, List<Student>> lis =
    students.stream().collect(
    Collectors.groupingBy(stu -> stu.getSpecialisies()+"***"+stu.getName()));
    System.out.println(lis);

    案例十三:

    /**
    * 常用的流:拼接joining 有三个参数,第一个是分隔符,第二个是前缀符,第三个是后缀符。也可以不传入参数Collectors.joining(),这样就是直接拼接。
    * 功能:类似stringbuilder这样循环append("a") append("b") append("c")拼接
    * 示例:将所有学生的名字拼接起来
    * 结果:[路飞,红发,白胡子]
    */
    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));

    String names = students.stream()
    .map(Student::getName).collect(Collectors.joining(",","[","]"));
    System.out.println(names);

    案例十四:

    /**
    * 接口:Consumer 顾名思义,它是“消费者的含义”,接受参数而不返回值
    * 示例:打印消息
    * 结果:hello world
    * hello java
    * hhhhh
    * hhhhh
    * hhhhh
    */
    Consumer c = System.out::println;
    c.accept("hello world");//打印hello world
    c.accept("hello java");//打印hello java
    c.andThen(c).andThen(c).accept("hhhhh");//连续打印三次hhhhh 而不是hello java hello java hhhhh

    案例十五:

    /**
    * 接口:Function 代表的含义是“函数”,其实和上面的 Consumer有点像,不过 Function既有输入,也有输出,使用更加灵活
    * 示例:对一个整数先乘以 2,再计算平方值
    * 结果:36 5184
    * 过程:先走apply传递参数3 然后执行f1=3*2得到6 然后执行f2=6*6得到36
    * 先走apply传递参数3 然后执行f1=3*2得到6 然后执行f2=6*6得到36 然后执行f1=36*2得到72 然后执行f2=72*72得到5184
    * andThen的参数就是 Function类型的after 即接下里执行的函数
    */
    Function<Integer,Integer> f1 = i -> i*2;
    Function<Integer,Integer> f2 = i -> i*i;
    Consumer c = System.out::println;

    c.accept(f1.andThen(f2).apply(3));
    c.accept(f1.andThen(f2).andThen(f1).andThen(f2).apply(3));

    案例十六:空值校验

    /**
    * 接口:Optional 本质是个容器,你可以将你的变量交由它进行封装,这样我们就不用显式对原变量进行 null值检测,防止出现各种空指针异常
    * 示例:获取学生科目的成绩
    */
    public static Integer getScore(Student stu){
    return Optional.ofNullable(stu).map(Student::getSubject).map(Subject::getScore).orElse(null);
    }
    //常规做法 判断学生是否为空,不为空得到学科,判断学科是否为空,不为空取值 如果有很多层包着 简直是俄罗斯套娃 惨不忍睹
    public static Integer getScore(Student stu){
    if(stu != null){
    Subject sub = stu.getSubject();
    if (sub != null){
    return sub.getScore();
    }
    }
    return null;
    }
  • 相关阅读:
    Batch Normalization
    常用shell命令
    把chord下dbm_noauth做成静态库,提供接口
    vim中多标签和多窗口的使用
    recv返回值
    在XP下从硬盘安装windows 7的方法
    Linux文件系统中的链接
    统计出现次数排名
    linux编程环境
    windows命令行修改连接的DNS
  • 原文地址:https://www.cnblogs.com/xuchao0506/p/13156925.html
Copyright © 2020-2023  润新知