Java8特性

接口的改变

  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());
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容