Java8新特性

1.Lamda表達式

Lambda表達式的作用主要是用來簡化接口的創(chuàng)建摊滔,使用Lambda表達式接口必須是函數(shù)式接口

  • 語法格式一:無參,無返回值店乐,Lambda體只需一條語句
  • 語法格式二:Lambda只需要一個參數(shù)時艰躺,參數(shù)的小括號可以省略
  • 語法格式三:當Lambda體只有一條語句時,return與大括號可以省略
  • 語法格式四:參數(shù)的數(shù)據(jù)類型可以省略
@Test
public void testLambda() {
    new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            log.info(" {} ", i);
        }
    }).start();
}

2.函數(shù)式接口

函數(shù)式接口只能有一個抽象方法眨八,使用@FunctionalInterface注解可以檢查是否是函數(shù)式接口

  • 自定義函數(shù)式接口
@FunctionalInterface
interface MyFunc<T> {
    T getValue(T t);
}
  • 四大內(nèi)置核心函數(shù)式接口

Consumner<T> : 消費型接口

void accept(T t);

用途:對類型為T的對象應(yīng)用操作腺兴,包含方法:void accept(T t);

@Test
public void testConsume() {
    pay(1000, money -> System.out.println("購物消費了" + money + "元"));
}

private void pay(int money, Consumer<Integer> consumer) {
    consumer.accept(money);
}

Supplier<T> :供給型接口

T get();

用途:返回類型為T的對象,包含方法:T get();

@Test
public void testSupplier() {
    List<Integer> list = getNumList(10, () -> (int)(Math.random() * 100));
    for (int num : list) {
        System.out.println("supplier" + num);
    }
}

private List<Integer> getNumList(int num, Supplier<Integer> supplier) {
    List<Integer> list = new ArrayList<>();

    for (int i = 0; i < num; i++) {
        list.add(supplier.get());
    }

    return list;
}

Function<T , R>:函數(shù)式接口

R apply(T t);

用途:對類型為T的對象應(yīng)用操作廉侧,并返回結(jié)果页响,結(jié)果是R類型的對象,包含方法:R apply(T t);

@Test
public void testFunction() {
    String name = "Jack Yang";
    System.out.print(strHandler(name, String::toLowerCase));
}
private String strHandler(String str, Function<String, String> func) {
    return func.apply(str);
}

Predicate<T>:斷言型接口

boolean test(T t);

用途:確定類型為T的對象是否滿足某約束段誊,并返回boolean值闰蚕,包含方法:boolean test(T t);

@Test
public void testPredicate() {
    List<String> list = filterStr(
        Arrays.asList("jackyang", "jackie", "jordan", "ronaldo", "figo", "zidane"),
        s -> s.length() >= 6
    );
    for (String name : list) {
        System.out.println(name);
    }
}

private List<String> filterStr(List<String> list, Predicate<String> predicate) {
    List<String> handleList = new ArrayList<>();
    for(String str : list) {
        if(predicate.test(str)) {
            handleList.add(str);
        }
    }
    return handleList;
}

其他函數(shù)式接口(http://www.runoob.com/java/java8-functional-interfaces.html)

3.方法引用

方法引用所引用的方法的參數(shù)列表與返回值類型,需要與函數(shù)式接口中抽象方法的參數(shù)列表和返回值類型保持一致

若Lambda 的參數(shù)列表的第一個參數(shù)枕扫,是實例方法的調(diào)用者陪腌,第二個參數(shù)(或無參)是實例方法的參數(shù)時,格式: ClassName::MethodName

構(gòu)造器的參數(shù)列表烟瞧,需要與函數(shù)式接口中參數(shù)列表保持一致

三種語法格式
  • 對象::實例方法
  • 類::靜態(tài)方法
  • 類::實例方法

4.Stream API

集合講的是數(shù)據(jù)诗鸭,流講的是計算!
  • Stream 自己不會存儲元素。
  • Stream 不會改變源對象参滴。相反强岸,他們會返回一個持有結(jié)果的新Stream。
  • Stream 操作是延遲執(zhí)行的砾赔。這意味著他們會等到需要結(jié)果的時候才執(zhí)行蝌箍。
Stream流的操作三個步驟
  • 創(chuàng)建流(數(shù)據(jù)源:集合、數(shù)組)
  • 中間操作(操作鏈暴心,對數(shù)據(jù)源數(shù)據(jù)進行計算)
  • 終止操作(產(chǎn)生結(jié)果)
創(chuàng)建Stream流
  • 集合創(chuàng)建流(Collection 接口擴展)

default Stream<E> stream() : 返回一個順序流

default Stream<E> parallelStream() : 返回一個并行流

  • 數(shù)組創(chuàng)建流(Arrays 靜態(tài)方法)

static <T> Stream<T> stream(T[] array): 返回一個流

  • 值創(chuàng)建流(靜態(tài)方法 Stream.of())

public static<T> Stream<T> of(T... values) : 返回一個流

  • 創(chuàng)建無限流(函數(shù)創(chuàng)建 iterate和generate)

迭代 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

生成 public static<T> Stream<T> generate(Supplier<T> s)

@Slf4j
public class StreamTest extends AdminApiApplicationTests {
    @Data
    class Student {
        private String name;
        private Integer age;

        public Student(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }

    @Test
    public void testStreamCreate() {
        System.out.println("-----------集合創(chuàng)建流-----------");
        Arrays.asList("jackyang", "", "jordan", "helloworld", "hellokitty").stream().filter(s -> s.length() > 8).forEach(System.out::println);

        System.out.println("-----------數(shù)據(jù)創(chuàng)建流-----------");
        Student[] students = new Student[]{
                new Student("jackyang", 30),
                new Student("jordan", 40),
                new Student("kitty", 18)
        };
        Arrays.stream(students).filter(student -> student.age > 20).forEach(System.out::println);

        System.out.println("-----------值創(chuàng)建流-----------");
        Stream.of(students).filter(student -> student.age < 20).forEach(System.out::println);

        System.out.println("-----------創(chuàng)建無限流-----------");
        Stream.iterate(5, s -> s + 2).limit(10).forEach(System.out::println);
        Stream.generate(() -> (int)(Math.random() * 100)).limit(10).forEach(System.out::println);
    }
}
中間操作

中間操作不會執(zhí)行任何的操作妓盲,而是在終止操作時一次性全部處理,稱為“惰性求值”

  • filter(Predicate p) 接收 Lambda 從流中排除某些元素
  • distinct() 通過流所生成元素的 hashCode() 和 equals() 去 除重復(fù)元素
  • limit(long maxSize) 截斷流专普,使其元素不超過給定數(shù)量
  • skip(long n) 跳過元素悯衬,返回一個剔除了前 n 個元素的流,若流中元素不足n個檀夹,則返回一個空流
  • map(Function f) 接收一個函數(shù)作為參數(shù)筋粗,該函數(shù)會被應(yīng)用到每個元素上,并將其映射成一個新的元素炸渡。
  • mapToDouble(ToDoubleFunction f) 接收一個函數(shù)作為參數(shù)娜亿,該函數(shù)會被應(yīng)用到每個元 素上,產(chǎn)生一個新的 DoubleStream
  • mapToInt(ToIntFunction f) 接收一個函數(shù)作為參數(shù)蚌堵,該函數(shù)會被應(yīng)用到每個元 素上买决,產(chǎn)生一個新的 IntStream
  • mapToLong(ToLongFunction f) 接收一個函數(shù)作為參數(shù),該函數(shù)會被應(yīng)用到每個元 素上吼畏,產(chǎn)生一個新的 LongStream
  • flatMap(Function f) 接收一個函數(shù)作為參數(shù)督赤,將流中的每個值都換成另一個流,然后把所有流連接成一個流
  • sorted() 產(chǎn)生一個新流宫仗,其中按自然順序排序
  • sorted(Comparator comp) 產(chǎn)生一個新流够挂,其中按比較器順序排序
終止操作

終止操作會從流的流水線生成結(jié)果,其結(jié)果可以是任何不是流的值藕夫,例如:List孽糖、Integer,甚至是 void

匹配

  • allMatch(Predicate p) 檢查是否匹配所有元素
  • anyMatch(Predicate p) 檢查是否至少匹配一個元素
  • noneMatch(Predicate p) 檢查是否沒有匹配所有元素

查找

  • findFirst() 返回第一個元素
  • findAny() 返回當前流中的任意元素
  • count() 返回流中元素總數(shù)
  • max(Comparator c) 返回流中最大值
  • min(Comparator c) 返回流中最小值

遍歷

  • forEach(Consumer c) 內(nèi)部迭代

規(guī)約

  • reduce(T iden, BinaryOperator b) 可以將流中元素反復(fù)結(jié)合起來毅贮,得到一個值办悟,返回 T
  • reduce(BinaryOperator b) 可以將流中元素反復(fù)結(jié)合起來,得到一個值滩褥,返回 Optional<T>

收集

  • collect(Collector c) 將流轉(zhuǎn)換為其他形式病蛉,接收一個 Collector接口的實現(xiàn)

用于給Stream中元素做匯總的方法

toList
List<T>
把流中元素收集到List
List<Employee> emps = list.stream().collect(Collectors.toList());

Set<T>
把流中元素收集到Set
Set<Employee> emps = list.stream().collect(Collectors.toSet());
 
toCollection
Collection<T>
把流中元素收集到創(chuàng)建的集合
Collection<Employee>emps =list.stream().collect(Collectors.toCollection(ArrayList::new));
 
counting
Long
計算流中元素的個數(shù)
long count = list.stream().collect(Collectors.counting());
 
summingInt
Integer
對流中元素的整數(shù)屬性求和
int total = list.stream().collect(Collectors.summingInt(Employee::getSalary));
 
averagingInt
Double
計算流中元素Integer屬性的平均 值
double avg = list.stream().collect(Collectors.averagingInt(Employee::getSalary));
 
summarizingInt
IntSummaryStatistics
收集流中Integer屬性的統(tǒng)計值。 如:平均值
IntSummaryStatistics iss = list.stream().collect(Collectors.summarizingInt(Employee::getSalary));

joining
String
連接流中每個字符串
String str = list.stream().map(Employee::getName).collect(Collectors.joining());
 
maxBy
Optional<T>
根據(jù)比較器選擇最大值
Optional<Emp>max = list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
 
minBy
Optional<T>
根據(jù)比較器選擇最小值
Optional<Emp> min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));

reducing
歸約產(chǎn)生的類型
從一個作為累加器的初始值開始,利用BinaryOperator與 流中元素逐個結(jié)合铺然,從而歸約成單個值
int total = list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));

collectingAndThen
轉(zhuǎn)換函數(shù)返回的類型
包裹另一個收集器俗孝,對其結(jié) 果轉(zhuǎn)換函數(shù)
int how = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
    
groupingBy
Map<K, List<T>>
根據(jù)某屬性值對流分組,屬 性為K魄健,結(jié)果為V
Map<Emp.Status, List<Emp>> map= list.stream() .collect(Collectors.groupingBy(Employee::getStatus));

partitioningBy
Map<Boolean, List<T>>
根據(jù)true或false進行分區(qū)
Map<Boolean,List<Emp>> vd = list.stream().collect(Collectors.partitioningBy(Employee::getManage));

5.并行流與串行流

并行流就是把一個內(nèi)容分成多個數(shù)據(jù)塊赋铝,并用不同的線程分別處理每個數(shù)據(jù)塊的流

可以使用parallel() 與 sequential() 在并行流與串行流之間進行切換

Fork/Join框架: 就是在必要的情況下,將一個大任務(wù)沽瘦,進行拆分(fork)成若干個小任務(wù)(拆到不可再拆時)革骨,再將一個個的小任務(wù)運算的結(jié)果進行join匯總.
采用 “工作竊取”模式(work-stealing): 當執(zhí)行新的任務(wù)時它可以將其拆分成更小的任務(wù)執(zhí)行,并將小任務(wù)加到線程隊列中析恋,然后再從一個隨機線程的隊列中偷一個并把它放在自己的隊列中

6.新時間日期 API

  • LocalDate
  • LocalTime
  • LocalDateTime
now() 靜態(tài)方法良哲,根據(jù)當前時間創(chuàng)建對象
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now();

of() 靜態(tài)方法,根據(jù)指定日期/時間創(chuàng)建 對象
LocalDate localDate = LocalDate.of(2016, 10, 26); 
LocalTime localTime = LocalTime.of(02, 22, 56); 
LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55);

plusDays, plusWeeks, plusMonths, plusYears 向當前 LocalDate 對象添加幾天助隧、 幾周筑凫、幾個月、幾年

minusDays, minusWeeks, minusMonths, minusYears 從當前 LocalDate 對象減去幾天喇颁、 幾周漏健、幾個月、幾年

plus, minus 添加或減少一個 Duration 或 Period

withDayOfMonth, withDayOfYear, withMonth, withYear 將月份天數(shù)橘霎、年份天數(shù)蔫浆、月份、年 份修改為指定的值并返回新的 LocalDate 對象

getDayOfMonth 獲得月份天數(shù)(1-31)

getDayOfYear 獲得年份天數(shù)(1-366)

getDayOfWeek 獲得星期幾(返回一個 DayOfWeek 枚舉值)

getMonth 獲得月份, 返回一個 Month 枚舉值

getMonthValue 獲得月份(1-12)

getYear 獲得年份

until 獲得兩個日期之間的 Period 對象姐叁, 或者指定 ChronoUnits 的數(shù)字

isBefore, isAfter 比較兩個 LocalDate

isLeapYear 判斷是否是閏年
  • Instant 時間戳

Duration:用于計算兩個時間間隔

Period:用于計算兩個日期間隔

  • TemporalAdjuster: 時間校正器
  • 時間格式化
@Test
public void testDateFormat() {
    LocalDateTime local = LocalDateTime.now();
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    System.out.println(formatter.format(local));
}

@Test
public void testDateFormat() {
    LocalDateTime local = LocalDateTime.now();
    String dateTime = local.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
    System.out.println(dateTime);
}

@Test
public void testDateFormat() {
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String strDate = "2018年05月12日 14:31:33";
    LocalDateTime ldt = LocalDateTime.now();
    LocalDateTime newDate = ldt.parse(strDate, dateTimeFormatter);
    System.out.println(newDate);
}

7.接口中默認方法與靜態(tài)方法

接口默認方法的類優(yōu)先原則

若一個接口中定義了一個默認方法瓦盛,而另外一個父類或接口中又定義了一個同名的方法時選擇父類中的方法

如果一個父類提供了具體的實現(xiàn),那么接口中具有相同名稱和參數(shù)的默認方法會被忽略

接口沖突:

如果一個父接口提供一個默認方法外潜,而另一個接口也提供了一個具有相同名稱和參數(shù)列表的方法(不管方法是否是默認方法)原环,那么必須覆蓋該方法來解決沖突

8.Optional類

常用方法:
Optional.of(T t) : 創(chuàng)建一個 Optional 實例

Optional.empty() : 創(chuàng)建一個空的 Optional 實例

Optional.ofNullable(T t):若 t 不為 null,創(chuàng)建 Optional 實例,否則創(chuàng)建空實例

isPresent() : 判斷是否包含值

orElse(T t) : 如果調(diào)用對象包含值,返回該值处窥,否則返回t

orElseGet(Supplier s) :如果調(diào)用對象包含值嘱吗,返回該值,否則返回 s 獲取的值

map(Function f): 如果有值對其處理滔驾,并返回處理后的Optional谒麦,否則返回 Optional.empty()

flatMap(Function mapper):與 map 類似,要求返回值必須是Optional

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哆致,一起剝皮案震驚了整個濱河市绕德,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摊阀,老刑警劉巖耻蛇,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踪蹬,死亡現(xiàn)場離奇詭異,居然都是意外死亡臣咖,警方通過查閱死者的電腦和手機跃捣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來亡哄,“玉大人枝缔,你說我怎么就攤上這事布疙∥霉撸” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵灵临,是天一觀的道長截型。 經(jīng)常有香客問我,道長儒溉,這世上最難降的妖魔是什么宦焦? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮顿涣,結(jié)果婚禮上波闹,老公的妹妹穿的比我還像新娘。我一直安慰自己涛碑,他們只是感情好精堕,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒲障,像睡著了一般歹篓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揉阎,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天庄撮,我揣著相機與錄音,去河邊找鬼毙籽。 笑死洞斯,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的坑赡。 我是一名探鬼主播烙如,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼垮衷!你這毒婦竟也來了厅翔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤搀突,失蹤者是張志新(化名)和其女友劉穎刀闷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡甸昏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年顽分,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片施蜜。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡卒蘸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翻默,到底是詐尸還是另有隱情缸沃,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布修械,位于F島的核電站趾牧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏肯污。R本人自食惡果不足惜翘单,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蹦渣。 院中可真熱鬧哄芜,春花似錦、人聲如沸柬唯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽权逗。三九已至美尸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斟薇,已是汗流浹背师坎。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留堪滨,地道東北人胯陋。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像袱箱,于是被迫代替她去往敵國和親遏乔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Java8新特性 Lambda表達式 概念 lambda表達式是一段可以傳遞的代碼发笔,它的核心思想是將面向?qū)ο笾械膫?..
    好好秦先生閱讀 823評論 0 1
  • 原創(chuàng)文章&經(jīng)驗總結(jié)&從校招到A廠一路陽光一路滄桑 詳情請戳www.codercc.com 對于Java開發(fā)者來說盟萨,...
    你聽___閱讀 2,337評論 4 38
  • source Description You are to write a program that has to...
    Gitfan閱讀 312評論 0 0
  • 切下一塊根莖 丟進小小的水杯 不經(jīng)意間 收獲滿滿一杯的豐盛
    禾小he閱讀 194評論 0 4