美文网首页
Java8特性

Java8特性

作者: spilledyear | 来源:发表于2018-09-19 23:02 被阅读0次

    接口的改变

    1. 接口中可以定义 static方法default方法,并且这两个方法都可以有方法体;
    2. static方法属于接口,default方法属于实例;
    3. static方法不会被继承,静态变量会被继承;
    4. 如果一个类实现了多个接口,并且这些接口相互之间没有继承关系,同时存在相同的默认方法,会报错:不相关默认配置;
    5. 如果一个类实现了多个接口,并且这些接口相互之间存在继承关系,同时存在相同的默认方法,默认方法会被子接口覆盖;
    6. 如果遇到有多个继承并且有相同的默认方法,实现类可以通过特殊语法指定要访问哪个接口的方法:在实现类中重写默认方法,然后通过以下语法:接口名.super.默认方法名;同理,这个规则也适应于接口;
    7. 如果一个接口只有一个抽象方法,那么这个接口属于函数式接口
    8. 如果一个接口使用@FunctionalInterface注解修饰,那么这个接口有且只有一个抽象方法(对static方法和default方法没有限制);
    9. 在接口里面可以使用default方法来实现父接口的抽象方法;
    public interface TsInface01 {
        static void staticMethod(){
            System.out.println("我是 TsInface01 接口中的static方法: staticMethod");
        }
        default void default1(){
            System.out.println("我是 TsInface01 接口中的default方法: default1");
        }
    }
    
    public interface TsInface02 extends TsInface01{
        static void staticMethod(){
            System.out.println("我是 TsInface02 接口中的static方法: staticMethod");
        }
    }
    
    public interface TsInface03 {
        static void staticMethod(){
            System.out.println("我是 TsInface03 接口中的static方法: staticMethod");
        }
    
        default void default1(){
            System.out.println("我是 TsInface03 接口中的default方法: default1");
        }
    
    }
    
    public class Test01 implements TsInface01, TsInface02 {
        public static void main(String[] args) {
            Test01 t01 = new Test01();
            t01.default1();
        }
    
        @Override
        public void default1(){
            TsInface02.super.default1();
        }
    }
    

    Lamba

    函数式接口,该接口中只能由一个抽象方法,可以使用@FunctionalInterface注解修饰某个接口有且仅有一个抽象方法。

    @FunctionalInterface
    public interface TsInface04 {
        void getName(String firstName);
    
        default void getMoney() {
            System.out.println("默认方法就是这么任性");
        }
    
        static void main(String[] args) {
            System.out.println("自从接口可以由静态方法,可以写main函数,作为程序的入口");
        }
    }
    

    使用:参数 + 规则 + 方法体
    如果使用局部变量,局部变量必须是final类型

    public class Test02 implements TsInface01, TsInface02 {
        public static void main(String[] args) {
            Test02 t02 = new Test02();
    
            // 参数 + 规则 + 方法体
            TsInface04 ts04 = (fisrtName) -> {
                return fisrtName + "bbbbbb";
            };
    
            // 只有一个参数的时候,参数中的那个括号可以省略
            TsInface04 ts05 = fisrtName -> {
                return fisrtName + "bbbbbb";
            };
    
            // 只有一句话的方法体,大括号 和 return 也可以省略
            TsInface04 ts06 = fisrtName -> fisrtName + "bbbbbb";
            
            System.out.println(ts04.getName("全写"));
            System.out.println(ts05.getName("简写"));
            System.out.println(ts06.getName("简简写"));
        }
    }
    

    方法引用

    import java.util.HashMap;
    import java.util.Map;
    
    @FunctionalInterface
    interface TsInface05 {
        String getName(String firstName);
        default void getMoney() {}
    }
    
    @FunctionalInterface
    interface TsInface06 {
        Map<String, String> getName(Map<String,String> map, String firstName);
    }
    
    @FunctionalInterface
    interface TsInface07 {
        void getName(Map<String,String> map, String firstName);
    }
    
    public class Test03 {
        public Test03(){
    
        }
        public Test03(Map<String,String> map, String firstName){
            map.put("NAME", firstName);
            System.out.println(map.get("NAME"));
        }
    
        public static void main(String[] args) {
            Test03 test03 = new Test03();
    
            // 引用实例的方法
            TsInface05 t501 = test03::getName1;
            t501.getName("引用实例的方法");
    
            // 引用类的方法
            TsInface05 t502 = Test03::getName2;
            t501.getName("引用类的方法");
    
            // 引用类实例方法
            Map<String, String> map = new HashMap<>(16);
            TsInface06 t601 = Test03::getName3;
            t601.getName(map, "引用类实例方法");
    
            // 引用构造方法
            TsInface07 t701 = Test03::new;
            t701.getName(map, "引用构造方法");
        }
    
    
        // 实例方法
        public String getName1(String str) {
            System.out.println(str);
            return str;
        }
    
        // 类方法
        public static String getName2(String str) {
            System.out.println(str);
            return str;
        }
    
        // 类实例方法
        public static Map<String, String> getName3(Map<String, String> map, String str) {
            map.put("NAME", str);
            System.out.println(map.get("NAME"));
            return map;
        }
    }
    

    Stream

    Stream详解

    Stream生成

    • 从 Collection 和 数组
      Collection.stream()
      Collection.parallelStream()
      Arrays.stream(T array) or Stream.of()

    • 从 BufferedReader
      java.io.BufferedReader.lines()

    • 静态工厂
      java.util.stream.IntStream.range()
      java.nio.file.Files.walk()

    • 自己构建
      java.util.Spliterator

    • 其它
      Random.ints()
      BitSet.stream()
      Pattern.splitAsStream(java.lang.CharSequence)
      JarFile.stream()

    // 1. Individual values
    Stream stream = Stream.of("a", "b", "c");
    // 2. Arrays
    String [] strArray = new String[] {"a", "b", "c"};
    stream = Stream.of(strArray);
    stream = Arrays.stream(strArray);
    // 3. Collections
    List<String> list = Arrays.asList(strArray);
    stream = list.stream();
    

    Stream操作

    流的操作类型分为三种:

    • Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。主要方法有:map(mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

    • Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。主要方法有:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

    • short-circuiting:主要应用于:对于一个intermediate操作,如果它接受的是一个无限大(infinite/unbounded)的Stream,但返回一个有限的新 Stream;对于一个 erminal操作,如果它接受的是一个无限大的Stream,但能在有限的时间计算出结果。主要方法有:anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

    在对于一个 Stream 进行多次转换操作(Intermediate 操作),每次都对 Stream 的每个元素进行转换,而且是执行多次,这样时间复杂度就是 N(转换次数)个 for 循环里把所有操作都做掉的总和吗?其实不是这样的,转换操作都是 lazy 的,多个转换操作只会在 Terminal 操作的时候融合起来,一次循环完成。我们可以这样简单的理解,Stream 里有个操作函数的集合,每次转换操作就是把转换函数放入这个集合中,在 Terminal 操作的时候循环 Stream 对应的集合,然后对每个元素执行所有的函数。

    int sum = widgets.stream()
    .filter(w -> w.getColor() == RED)
    .mapToInt(w -> w.getWeight())
    .sum();
    

    stream() 获取当前小物件的 source,filter 和 mapToInt 为 intermediate 操作,进行数据筛选和转换,最后一个 sum() 为 terminal 操作,对符合条件的全部小物件作重量求和。

    自定义Stream

    生成 10 个随机整数

    Random seed = new Random();
    Supplier<Integer> random = seed::nextInt;
    Stream.generate(random).limit(10).forEach(System.out::println);
    //Another way
    IntStream.generate(() -> (int) (System.nanoTime() % 100)).
    limit(10).forEach(System.out::println);
    

    Stream.generate() 还接受自己实现的 Supplier

    Stream.generate(new PersonSupplier()).
    limit(10).
    forEach(p -> System.out.println(p.getName() + ", " + p.getAge()));
    
    private class PersonSupplier implements Supplier<Person> {
        private int index = 0;
        private Random random = new Random();
    
        @Override
        public Person get() {
            return new Person(index++, "StormTestUser" + index, random.nextInt(100));
        }
    }
    

    时间API

    • LocalDate
    • LocalTime
    • LocalDateTime
    • DateTimeFormatter
    • ZonedDateTime
    package com.hand.sxy.java8.intface;
    
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    
    public class Test04 {
        public static void main(String[] args) {
            LocalDate d1 = LocalDate.now();
            System.out.println(d1.toString());
    
            LocalTime d2 = LocalTime.now();
            System.out.println(d2.toString());
    
            LocalDateTime d3 = LocalDateTime.now();
            System.out.println(d3.toString());
    
            DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            d3 = LocalDateTime.parse("2018-09-19 11:23:22", f);
            System.out.println(d3.toString());
    
            ZonedDateTime zd = ZonedDateTime.now();
            zd.format(f);
            System.out.println(zd.toString());
        }
    }
    

    相关文章

      网友评论

          本文标题:Java8特性

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