美文网首页
1.8新特性

1.8新特性

作者: jiahzhon | 来源:发表于2021-03-11 16:21 被阅读0次

    lamda

    • Lambda表达式(闭包),Lambda允许把函数作为一个方法的参数(函数作为参数传递方法中),或者把代码看成数据。Lamda表达式用于简化Java中接口式的匿名内部类。被称为函数式接口的概念。函数式接口就是一个具有 一个方法 的普通接口。像这样的接口可以被隐式的转换成Lambda表达式。

    • 格式

    (parameters) -> expression
    或
    (parameters) ->{ statements; }
    
    • 例子
    public class Java8Tester {
       public static void main(String args[]){
          Java8Tester tester = new Java8Tester();
            
          // 类型声明
          MathOperation addition = (int a, int b) -> a + b;
            
          // 不用类型声明
          MathOperation subtraction = (a, b) -> a - b;
            
          // 大括号中的返回语句
          MathOperation multiplication = (int a, int b) -> { return a * b; };
            
          // 没有大括号及返回语句
          MathOperation division = (int a, int b) -> a / b;
            
          System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
          System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
          System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
          System.out.println("10 / 5 = " + tester.operate(10, 5, division));
            
          // 不用括号
          GreetingService greetService1 = message ->
          System.out.println("Hello " + message);
            
          // 用括号
          GreetingService greetService2 = (message) ->
          System.out.println("Hello " + message);
            
          greetService1.sayMessage("Runoob");
          greetService2.sayMessage("Google");
       }
        
       interface MathOperation {
          int operation(int a, int b);
       }
        
       interface GreetingService {
          void sayMessage(String message);
       }
        
       private int operate(int a, int b, MathOperation mathOperation){
          return mathOperation.operation(a, b);
       }
    }
    
    • 对字符串数组按字符串长度排序
    package org.xxxx.demo01;
     
    import java.util.Arrays;
    import java.util.Comparator;
     
    public class Demo01 {
        public static void main(String[] args) {
            // 定义字符串数组
            String[] strArr = { "abc", "cd", "abce", "a" };
     
            // 传统方法
            // 匿名内部类
            Arrays.sort(strArr, new Comparator<String>() {
     
                @Override
                public int compare(String s1, String s2) {
                    return Integer.compare(s2.length(), s1.length());
                }
            });
     
            // 输出排序结果
            for (String s : strArr) {
                System.out.println(s);
            }
            System.out.println("---------------------");
     
            // Lambda表达式
            Arrays.sort(strArr, (s1, s2) -> Integer.compare(s2.length(), s1.length()));
     
            // 输出
            for (String s : strArr) {
                System.out.println(s);
            }
        }
    }
    
    • 用Lambda实现多线程
    package org.xxxx.demo01;
     
    public class Demo01 {
        public static void main(String[] args) {
            // Lambda表达式
            new Thread(() -> System.out.println(1 + "hello world")).start();
     
            System.out.println("----------------");
     
            // 方法体
            new Thread(() -> {
                for (int i = 0; i < 10; i++) {
                    System.out.println(2 + "hello world");
                }
            }).start();
        }
    }
    

    函数式接口

    • @FunctionalInterface:该注解是定义一个lambda表达式的基础, 即是否是函数式接口可以标注也可以不标注。
    • 函数式接口分类
      • 系统与定义函数接口(Comparator, Runnable)
      • 用户自定义函数接口(注解必须有,表达式是直接通过参数列表来实现的,只能有一个有效方法)
    @FunctionalInterface
    public interface MyInterface {
        String info(String tip);
    }
    
    • 公共定义的函数式接口

    • Function<T, R>

      • 有输入参数,有返回值
      • 是对接收一个T类型参数,返回R类型的结果的方法的抽象
      • 通过调用apply方法执行内容
      • 例子:给定一个字符串,返回字符串长度
    package org.xxxx.demo01;
     
    import java.util.function.Function;
     
    public class Demo01 {
        public static void main(String[] args) {
            // 定义字符串
            String str = "helloworld";
            
            // 调用方法
            // 在调用的时候写方法体,方法比较灵活
            int length = testFun(str, (s) -> s.length());
            
            System.out.println(length);
        }
        
        // 方法
        /**
         * 
         * @param str 输入参数
         * @param fun 表达式 String 为输入类型,Integer为输出类型
         * @return 返回字符串长度
         */
        public static int testFun(String str, Function<String, Integer> fun) {
            // 执行
            Integer length = fun.apply(str);
            
            return length;
        }
    }
    
    • 消费型接口:Consumer<T>
      • 有输入参数,没返回值
      • Consumer 使用accept对参数执行行为
      • 例子:输出字符串
    
    package org.xxxx.demo01;
     
    import java.util.function.Consumer;
     
    public class Demo01 {
        public static void main(String[] args) {
            // 创建字符串
            String str = "hello world";
            
            // 调用
            testCon(str, (s) -> System.out.println(s));
        }
        
        /**
         * 
         * @param str 传入参数
         * @param con
         */
        public static void testCon(String str, Consumer<String> con) {
            // 执行
            con.accept(str);
        }
    
    • 供给型接口:Supplier<T>
      • 无传入参数,有返回值
      • 该接口对应的方法类型不接受参数,但是提供一个返回值
      • 使用get()方法获得这个返回值
    package org.xxxx.demo01;
     
    import java.util.function.Supplier;
     
    public class Demo01 {
        public static void main(String[] args) {
            // 创建字符串
            String str = "hello world";
            
            // 调用
            String sup = testSup(() -> str);
            
            System.out.println(sup);
        }
        
        /**
         * 
         * @param sup
         * @return
         */
        public static String testSup(Supplier<String> sup) {
            // 执行
            String s = sup.get();
            return s;
        }
    
    • 断言型接口:Predicate<T>
      • 有传入参数,有返回值Boolean
      • 该接口对应的方法为接收一个参数,返回一个Boolean类型值
      • 多用于判断与过滤,使用test()方法执行这段行为
      • 需求:输入字符串,判断长度是否大于0
    package org.xxxx.demo01;
     
    import java.util.function.Predicate;
     
    public class Demo01 {
        public static void main(String[] args) {
            // 创建字符串
            String str = "hello world";
            
            // 调用
            boolean flag = testPre(str, (s) -> s.length() > 0);
            
            System.out.println(flag);
        }
        
        /**
         * 
         * @param str
         * @param pre
         * @return
         */
        public static boolean testPre(String str, Predicate<String> pre) {
            // 执行
            boolean flag = pre.test(str);
            
            return flag;
        }
    }
    

    方法引用

    • 某些lambda表达式里面仅仅是调用了一个已存在的方法,在这种情况下

    • 直接通过方法名称引用方法的形式可读性更高一些,这种形式就是方法引用

    • 方法引用是一种更简洁易懂的lambda 表达式替换

    image.png
    • 方法引用中::后只是方法名,不能加();
    import java.util.ArrayList;
    import java.util.List;
     
    public class Demo01 {
        public static void main(String[] args) {
            // 创建集合
            List<String> list = new ArrayList<>();
            
            // 添加元素
            list.add("e");
            list.add("c");
            list.add("a");
            list.add("d");
            list.add("b");
            
            // 排序
            list.sort((s1, s2) -> s1.compareTo(s2));
            
            // 遍历
            list.forEach((s) -> System.out.println(s));
            list.forEach(System.out::println);
        }
    }
    

    Stream

    • 是用函数式编程方式在集合类上进行复杂操作的工具,更像一个高级版本的 Iterator

    • 而和迭代器又不同的是,Stream 可以并行化操作

    • 在Java1.8 中, 集合接口提供了两个方法来生成流:stream()串行流和parallelStream()并行流,即Stream的操作可以分为串行stream()和并行parallelStream()。举个例子来说:

    List<String> strings = Arrays.asList("who","what","when","why","which");
    List<String> filterd = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
    
    • forEach 循环
           List<String> stringList = Arrays.asList("who","what","when","why","which");
    
            // 方式一:JDK1.8之前的循环方式
            for(String string:stringList){
                System.out.println(string);
            }
    
            // 方式二:使用Stream的forEach方法
            stringList.stream().forEach(e -> System.out.println(e));
    
            // 方式三:方式二的简化形式,因为方法引用也属于函数式接口,因此Lambda表达式可以用方法引用来代替
            stringList.stream().forEach(System.out::println);
    
    • filter 过滤
      • filter方法用于通过设置条件来过滤出满足条件的元素。举个例子来说,下面就是用于输出字符串列表中的空字符串的个数:
            List<String> stringList = Arrays.asList("","welcome","","to","visit","my","","website");
            long count = stringList.stream().filter(e -> e.isEmpty()).count();
            System.out.println(count);
    
    • map 映射
      • 是一种函数,用于映射每个元素执行某些操作得到对应的结果。举个例子来说,下面就是使用map来输出元素对应的平方数:
            List<Integer> integerList = Arrays.asList(2,3,4,5,6);
            List<Integer> integers = integerList.stream().map(i->i*i).collect(Collectors.toList());
            integerList.stream().forEach(System.out::println);
    
    • flatMap 映射
      • flatMap映射和map映射类似,不过它的每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中,说白了就是将几个小的list合并成一个大的list。
            List<String> fruitList = Arrays.asList("banana","orange","watermelon");
            List<String> vegetableList = Arrays.asList("kale","leek","carrot");
            List<String> transportList = Arrays.asList("car","bike","train");
            
            //将多个元素合成一个复合类型集合,元素类型List<String>
            List<List<String>> lists = Stream.of(fruitList,vegetableList,transportList).collect(Collectors.toList());
    
            //将多个元素合成一个单一类型集合,元素类型String
            List<String> flatMap = Stream.of(fruitList,vegetableList,transportList)
                    .flatMap(list ->list.stream())
                    .collect(Collectors.toList());
            System.out.println(flatMap);
    
    • sorted 排序
      • sorted方法用于对流进行排序。举个例子来说,下面的代码就是用于对字符串按照给定的规则进行排序并输出:
            List<String> stringList = Arrays.asList("c","a","f","d","b","e");
            stringList.stream().sorted((s1,s2) -> s1.compareTo(s2)).forEach(System.out::println);
    
    • distinct
      • 缺点就是不能设置去重的条件
            List<String> stringList = Arrays.asList("do","what","you","want","to","do","and","do","it");
            stringList.stream().distinct().forEach(System.out::println);
    
    • of 生成Stream对象
      • of方法用于生成Stream对象,注意它是Stream对象的方法。举个例子来说:
            Stream<Object> objectStream= Stream.of("do","what","you","want","to","do","and","do","it");
            objectStream.forEach(System.out::println);
    
    • count 计算总数
      • count方法用于计算流中元素的总数。举个例子来说:
            Stream<Object> objectStream = Stream.of("do","what","you","want","to","do","and","do","it");
            long count = objectStream.count();
            System.out.println(count);
    
    • min和max 最小/最大
      • collect方法的使用较为复杂,这里仅仅介绍一些常用的方法即可。collect方法可以将Stream转为Collection对象或者是Object类型的数组等,举个例子来说:
            List<String> stringList= Arrays.asList("do","what","you","want","to","do","and","do","it");
            //Stream转Collection
            stringList.stream().collect(Collectors.toList());
            //Stream转Object[]数组
            Object[] objects = stringList.stream().toArray();
    
    • collect
      • collect方法的使用较为复杂,这里仅仅介绍一些常用的方法即可。collect方法可以将Stream转为Collection对象或者是Object类型的数组等,举个例子来说:
            List<String> stringList= Arrays.asList("do","what","you","want","to","do","and","do","it");
            //Stream转Collection
            stringList.stream().collect(Collectors.toList());
            //Stream转Object[]数组
            Object[] objects = stringList.stream().toArray();
    

    相关文章

      网友评论

          本文标题:1.8新特性

          本文链接:https://www.haomeiwen.com/subject/swbnqltx.html