java8新特性

java8新特性

Lambda(核心)

用于快速的實現(xiàn)匿名內部類中的方法头谜。

例子:
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("do something.");      
    }
}

如果我們想要寫一些線程,而每個線程中的實現(xiàn)很簡單,就像例子中的只在控制臺打印一句話悴品,那么還需要多寫4行代碼,很麻煩简烘,可讀性也不高苔严。下面,看下lambda的實現(xiàn):

Runnable r = () -> System.out.println("do something.");
lambda的基礎語法:
expression = (variable) -> action
  • variable:可以是一個變量孤澎,一個占位符届氢,也可以是多個變量(x,y,z)。

  • action:實現(xiàn)的代碼邏輯覆旭,如果一行處理不完退子,可以用“{}”將執(zhí)行的代碼包起來岖妄。

  • expression:返回的值。

使用姿勢:
public class FunctionInterfaceDemo {
    @FunctionalInterface
    interface Predicate<T> {
        boolean test(T t);
    }
    /**
     * 執(zhí)行Predicate判斷
     *
     * @param age       年齡
     * @param predicate Predicate函數(shù)式接口
     * @return          返回布爾類型結果
     */
    public static boolean doPredicate(int age, Predicate<Integer> predicate) {
        return predicate.test(age);
    }
     
    public static void main(String[] args) {
        boolean isAdult = doPredicate(20, x -> x >= 18);
        System.out.println(isAdult);
    }
}

如上述代碼所示寂祥,當一個接口類中只有一個方法荐虐,且接口類作為變量傳入函數(shù)中的時候,就可以使用lambda函數(shù)丸凭。

四大內置接口

java8為lambda提供了4大內置接口福扬,分別消費型接口、供給型接口惜犀、函數(shù)型接口铛碑、斷言型接口。其它的很多接口都是這四種接口衍生出來的虽界,我們可以根據(jù)入?yún)⒑统鰠㈩愋偷牟煌`活使用汽烦。

消費型接口示例(只有入?yún)?:

//消費money
public static void donation(Integer money, Consumer<Integer> consumer){
    consumer.accept(money);  
}
public static void main(String[] args) {
    donation(1000, money -> System.out.println("好心的麥樂迪為Blade捐贈了"+money+"元")) ;
}

供給型接口示例(只有出參):

//傳入隨機數(shù),返回集合
public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
       List<Integer> resultList = new ArrayList<Integer>()   ;
       for(int x=0;x<num;x++)  
           resultList.add(supplier.get());
       return resultList ;
}
public static void main(String[] args) {
    List<Integer> list = supply(10,() -> (int)(Math.random()*100));
    list.forEach(System.out::println);
}

函數(shù)型接口示例(入?yún)⒊鰠⒍加?:

//轉換字符串為Integer
public static Integer convert(String str, Function<String, Integer> function) {
    return function.apply(str);
}
public static void main(String[] args) {
    Integer value = convert("28", x -> Integer.parseInt(x));
}    

斷言型接口示例(有入?yún)⑴遥鰠閎oolean類型):

//篩選出只有兩個字的水果
public static List<String> filter(List<String> fruit, Predicate<String> predicate){
    List<String> f = new ArrayList<>();
    for (String s : fruit) {
        if(predicate.test(s)){
            f.add(s);
        }
    }
    return f;
}
public static void main(String[] args) {
    List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴蓮", "火龍果", "水蜜桃");
    List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
    System.out.println(newFruit);
}

stream流

用于快速處理集合的數(shù)據(jù)(一般用于查找過濾)

創(chuàng)建流

我們常用的創(chuàng)建流的方式有兩種刹缝,一是集合創(chuàng)建流(最常用),二是數(shù)組創(chuàng)建流颈将,也有其它方式創(chuàng)建流梢夯,但是一般不用。

//1. 通過集合創(chuàng)建stream(推薦)
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

//2. 通過Arrays中的靜態(tài)方法
Integer[] intArray = new Integer[10];
Stream<Integer> stream2 = Arrays.stream(intArray);
處理過程
  1. 獲取流晴圾。
  2. 中間操作颂砸。
  3. 終止操作。

常見的流處理函數(shù)

/**
 * Stream的中間操作:
     * filter:排除元素
     * distinct:去重
     * limit:給定數(shù)量
     * skip:跳過幾個數(shù)量
     * map:實現(xiàn)函數(shù)
     * flatMap:扁平化
     * sorted:排序
 * Stream的終止操作:
     * allMatch,anyMatch,noneMatch:是否匹配元素
     * findFirst,findAny:返回元素
     * count,max,min:計數(shù)死姚,最大人乓,最小
     * forEach:迭代
     * reduce:歸約
 */
并行流

java7中的Fork/Join框架,會將一個大任務拆分成多個小任務都毒,并行的去執(zhí)行色罚,然后將各個小任務執(zhí)行的結果進行合并,最終返回結果账劲。缺點是代碼太難寫戳护,每實現(xiàn)一次要寫好多定制化的代碼。

java8中提供了并行流的方式瀑焦,底層用的就是Fork/Join框架腌且,但只需要一句代碼:

list.parallelStream()

與java7相比,人性化了很多榛瓮。

總結
  1. stream流函數(shù)中需要傳入的參數(shù)都是java8內置的lambda接口铺董,因此,推薦在函數(shù)中直接寫lambda禀晓。
  2. stream形式適用于集合數(shù)據(jù)快速的查找過濾等操作精续,當需要對集合中的數(shù)據(jù)進行很多的業(yè)務邏輯處理的時候坝锰,建議使用增強for循環(huán)。主要原因是lamdba寫法不適合寫的過長驻右,處理過多業(yè)務邏輯什黑,不利于后期維護。
練習
List<Transaction> transactions = null;

@Before
public void before(){
    //交易員
    Trader raoul = new Trader("Raoul", "Cambridge");
    Trader mario = new Trader("Mario", "Milan");
    Trader alan = new Trader("Alan", "Cambridge");
    Trader brian = new Trader("Brian", "Cambridge");

    //交易
    transactions = Arrays.asList(
            new Transaction(brian, 2011, 300),
            new Transaction(raoul, 2011, 1000),
            new Transaction(raoul, 2011, 400),
            new Transaction(mario, 2012, 710),
            new Transaction(mario, 2012, 700),
            new Transaction(alan, 2012, 950)
    );
}

/**
 * 1. 找出2011年發(fā)生的所有交易堪夭, 并按交易額排序(從低到高)
 */
@Test
public void test1() {
    transactions.stream()
            .filter((t) -> t.getYear() == 2011)
            .sorted(Comparator.comparingInt(Transaction::getValue))
            .forEach(System.out::println);
}

/**
 * 2. 交易員都在哪些不同的城市工作過愕把?
 */
@Test
public void test2() {
    transactions.stream()
            .map((e) -> e.getTrader().getCity())
            .distinct()
            .forEach(System.out::println);
}

/**
 * 3. 查找所有來自劍橋的交易員,并按姓名排序
 */
@Test
public void test3() {
    transactions.stream()
            .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
            .map((e) -> e.getTrader().getName())
            .sorted(Comparator.naturalOrder())
            .distinct()
            .forEach(System.out::println);
}

/**
 * 4. 返回所有交易員的姓名字符串森爽,按字母順序排序
 */
@Test
public void test4() {
    transactions.stream()
            .map((e) -> e.getTrader().getName())
            .sorted(Comparator.naturalOrder())
            .forEach(System.out::println);
}

/**
 * 5. 有沒有交易員是在米蘭工作的
 */
@Test
public void test5() {
    boolean b = transactions.stream()
            .anyMatch((e) -> e.getTrader().getCity().equals("Milan"));
    System.out.println(b);
}

/**
 * 6. 打印生活在劍橋的交易員的所有交易額之和
 */
@Test
public void test6() {
    Optional<Integer> optional = transactions.stream()
            .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
            .map(Transaction::getValue)
            .reduce(Integer::sum);
    System.out.println(optional.get());
}

/**
 * 7. 所有交易中恨豁,最高的交易額是多少
 */
@Test
public void test7() {
    Optional<Integer> optional = transactions.stream()
            .map(Transaction::getValue)
            .max(Integer::compareTo);
    System.out.println(optional.get());
}

/**
 * 8. 找到交易額最小的交易
 */
@Test
public void test8() {
    Optional<Transaction> optional = transactions.stream()
            .min(Comparator.comparingInt(Transaction::getValue));
    System.out.println(optional.get());
}

時間API

簡介
  1. java8對時間的api做了整理,主要為下面這三個類:LocalDate, LocalTime, LocalDateTime爬迟。從類名就可以看出橘蜜,一個是日期,一個是時間付呕,一個是全有计福。
  2. 我們平時使用的時候,盡量使用LocalDateTime徽职。
  3. 在java8之前象颖,我們使用的時間戳日期轉換工具SimpleDateFormat是線程不安全的,在使用的時候沒法抽成一個靜態(tài)工具類姆钉,需要在每一個線程下重新new一個SimpleDateFormat说订。java8中提供的DateTimeFormatter則是線程安全的。
開發(fā)中常用例子

1--獲取當前時間戳

@Test
public void test1() {
    //包含了日期和時間潮瓶,可以轉成秒陶冷,毫秒
    Instant timestamp = Instant.now();
    System.out.println(timestamp);
    //毫秒
    long milli = timestamp.toEpochMilli();
    System.out.println(milli);
    long second = timestamp.getEpochSecond();
    System.out.println(second);

}

2--時間戳與需要的日期格式相互轉換

/**
 * 2.1 時間戳轉成想要的日期格式
 */
@Test
public void test2() {
    String pattern = "yyyy-MM-dd HH:mm:ss";
    long time = Instant.now().toEpochMilli();
    //時間戳轉成日期
    //1. 時間戳轉成標準日期
    LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
    System.out.println(localDateTime);
    //2. 標準日期轉成我們需要的格式
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    String format = df.format(localDateTime);
    System.out.println(format);
}

/**
 * 2.2 給定任意日期格式轉成時間戳
 */
@Test
public void test3() {
    String pattern = "yyyy-MM-dd HH:mm:ss";
    //1. 將日期格式轉成標準日期
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    LocalDateTime localDateTime = LocalDateTime.parse("2018-12-17 10:00:00", df);
    System.out.println(localDateTime);
    //2. 轉換成時間戳
    long milli = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    System.out.println(milli);

}

3--時間日期差計算

/**
 * 3.1 計算時間差
 */
@Test
public void test4() throws InterruptedException {
    Instant ins1 = Instant.now();
    System.out.println(ins1.toEpochMilli());
    Thread.sleep(1000);
    Instant ins2 = Instant.now();
    System.out.println(ins2.toEpochMilli());
    long milli = Duration.between(ins1, ins2).toMillis();
    System.out.println(milli);
}


/**
 * 3.2 計算日期差
 */
@Test
public void test5() {
    LocalDate now = LocalDate.now();
    System.out.println(now);
    LocalDate birth = LocalDate.of(1994, 11,26);
    System.out.println(birth);
    //相隔日期
    Period period = Period.between(birth, now);
    System.out.println(period.getYears() + "-" + period.getMonths() + "-" + period.getDays());
    //相隔多少天
    long dayDiff = ChronoUnit.DAYS.between(birth, now);
    System.out.println(dayDiff);
}

4--日期加減

@Test
public void test6() {
    LocalDateTime today = LocalDateTime.now();
    LocalDateTime tor = today.plusDays(1);
    LocalDateTime yes = today.minusDays(1);
    System.out.println(yes);
    System.out.println(today);
    System.out.println(tor);
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市毯辅,隨后出現(xiàn)的幾起案子埂伦,更是在濱河造成了極大的恐慌,老刑警劉巖思恐,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沾谜,死亡現(xiàn)場離奇詭異,居然都是意外死亡壁袄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門媚媒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嗜逻,“玉大人,你說我怎么就攤上這事缭召≌磺辏” “怎么了逆日?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長萄凤。 經(jīng)常有香客問我室抽,道長,這世上最難降的妖魔是什么靡努? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任坪圾,我火速辦了婚禮,結果婚禮上惑朦,老公的妹妹穿的比我還像新娘兽泄。我一直安慰自己,他們只是感情好漾月,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布病梢。 她就那樣靜靜地躺著,像睡著了一般梁肿。 火紅的嫁衣襯著肌膚如雪蜓陌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天吩蔑,我揣著相機與錄音钮热,去河邊找鬼。 笑死哥纫,一個胖子當著我的面吹牛霉旗,可吹牛的內容都是我干的。 我是一名探鬼主播蛀骇,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厌秒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了擅憔?” 一聲冷哼從身側響起鸵闪,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎暑诸,沒想到半個月后蚌讼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡个榕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年篡石,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片西采。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡凰萨,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情胖眷,我是刑警寧澤武通,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站珊搀,受9級特大地震影響冶忱,放射性物質發(fā)生泄漏。R本人自食惡果不足惜境析,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一囚枪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧簿晓,春花似錦眶拉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谒臼,卻和暖如春朝刊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜈缤。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工拾氓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人底哥。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓咙鞍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親趾徽。 傳聞我的和親對象是個殘疾皇子续滋,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容

  • java8新特性 原創(chuàng)者:文思 一、特性簡介 速度更快 代碼更少孵奶,增加了Lambda 強大的Stream API ...
    文思li閱讀 3,047評論 1 1
  • 一疲酌、重要數(shù)據(jù)結構和JVM的改動 1.HashMap的改動 HashMap維護了一個Entry數(shù)組,put(K ke...
    一只愛java的貓閱讀 471評論 0 0
  • 前言: 北京時間2018年9月26日,Oracle官方發(fā)布Java 11了袁。既然版本都更新到11了朗恳,現(xiàn)在才來學8是不...
    貪挽懶月閱讀 997評論 0 16
  • 對于Java開發(fā)者來說,Java8的版本顯然是一個具有里程碑意義的版本载绿,蘊含了許多令人激動的新特性粥诫,如果能利用好這...
    jackcooper閱讀 1,025評論 0 6
  • 對于Java開發(fā)者來說,Java8的版本顯然是一個具有里程碑意義的版本崭庸,蘊含了許多令人激動的新特性怀浆,如果能利用好這...
    huanfuan閱讀 558評論 0 9