java8新特性

1.lambda表達(dá)式

? ? ? ? ? Lambda 允許把函數(shù)作為參數(shù)傳遞進(jìn)方法中

? ? ? ? ? // 類(lèi)型聲明 MathOperation addition = (int a, int b) -> a + b;?

? ? ? ? ? // 不用類(lèi)型聲明 MathOperation subtraction = (a, b) -> a - b;

? ? ? ? ? // 大括號(hào)中的返回語(yǔ)句 MathOperation multiplication = (int a, int b) -> { return a * b; };

? ? ? ? ? Lambda 表達(dá)式只能引用標(biāo)記了 final 的外層局部變量,lambda 表達(dá)式的局部變量可以不用聲明為 final史翘,但是必須不可被后面的代碼修改

? ? 2.方法引用

? ? ? ? 構(gòu)造器引用:它的語(yǔ)法是Class::new柜裸,或者更一般的Class< T >::new

? ? ? ? public static Car create(final Supplier<Car> supplier) { return supplier.get(); }

? ? ? ? final Car car = Car.create( Car::new );

? ? ? ? 靜態(tài)方法引用:它的語(yǔ)法是Class::static_method

? ? ? ? public static void collide(final Car car) { System.out.println("Collided " + car.toString()); }

? ? ? ? cars.forEach( Car::collide );

? ? ? ? 特定類(lèi)的任意對(duì)象的方法引用:它的語(yǔ)法是Class::method

? ? ? ? public void repair() { System.out.println("Repaired " + this.toString()); }

? ? ? ? cars.forEach( Car::repair );

? ? ? 特定對(duì)象的方法引用:它的語(yǔ)法是instance::method

? ? ? public void follow(final Car another) { System.out.println("Following the " + another.toString()); }

? ? ? final Car police = Car.create( Car::new );

? ? ? cars.forEach( police::follow );

? ? 3.Stream

? ? ? ? Stream(流)是一個(gè)來(lái)自數(shù)據(jù)源的元素隊(duì)列并支持聚合操作

? ? ? ? 數(shù)據(jù)源?流的來(lái)源拗馒。 可以是集合,數(shù)組,I/O channel味悄, 產(chǎn)生器generator 等。

? ? ? ? 聚合操作?類(lèi)似SQL語(yǔ)句一樣的操作, 比如filter, map, reduce, find, match, sorted等旗国。

? ? ? ? forEach? ? limit? ? sorted?

? ? ? ? Random random = new Random();

? ? ? ? random.ints().limit(10).sorted().forEach(System.out::println);

? ? ? ? map

? ? ? ? List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

? ? ? ? // 獲取對(duì)應(yīng)的平方數(shù)

? ? ? ? List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

? ? ? ? filter

? ? ? ? List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

? ? ? ? // 獲取空字符串的數(shù)量

? ? ? ? long count = strings.stream().filter(string -> string.isEmpty()).count();

? ? ? ? Collectors

? ? ? ? List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");

? ? ? ? List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

? ? ? ? System.out.println("篩選列表: " + filtered);

? ? ? ? String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));

? ? ? ? System.out.println("合并字符串: " + mergedString);

(1)Stream創(chuàng)建

1) 通過(guò)參數(shù)序列創(chuàng)建Stream

// 利用可變參數(shù)直接構(gòu)造Stream,相比Arrays.stream()更簡(jiǎn)單

// 下面語(yǔ)句創(chuàng)建的流內(nèi)容:10,20,30,40,50

final IntStream stream = IntStream.of(10, 20, 30, 40, 50);

// 下面語(yǔ)句創(chuàng)建的流內(nèi)容:red,blue,green

final Stream<String> colorStream = Stream.of("red", "blue", "green");

2) 通過(guò)數(shù)組創(chuàng)建Stream

相比Stream.of()注整,不用區(qū)分基礎(chǔ)數(shù)據(jù)類(lèi)型能曾,但參數(shù)只能是數(shù)組,不支持參數(shù)序列創(chuàng)建

final Integer[] numbers = {10, 20, 30, 40, 50, 60};

final Stream<Integer> numberStream = Arrays.stream(numbers);

final int[] intNumbers = {10, 20, 30, 40, 50, 60};

final IntStream result = Arrays.stream(intNumbers);

3) 通過(guò)集合創(chuàng)建Stream

final Collection<Integer> collection = Lists.newArrayList(10, 20, 30, 40, 50, 60);

final Stream<Integer> numberStream = collection.stream();

4) 通過(guò)集合創(chuàng)建并行Stream

final Collection<Integer> numbers = Lists.newArrayList(10, 20, 30, 40, 50, 60);

// 直接創(chuàng)建并行流

Stream<Integer> numberStream = numbers.parallelStream();

// 將串行流轉(zhuǎn)換為并行流

numberStream = numbers.stream().parallel();

5) 通過(guò)IO方式創(chuàng)建Stream

// 讀取文件的內(nèi)容肿轨,生成stream流

final Stream<String> stream = Files.lines(Paths.get("data.txt"), Charsets.UTF_8);

// 獲取目錄下的文件列表信息

final Stream<Path> listFile = Files.list(Paths.get("/"));

6) 通過(guò)生成器創(chuàng)建Stream

SecureRandom random = SecureRandom.getInstanceStrong();

// 直接傳入instance::method

// 下面語(yǔ)句創(chuàng)建的result包含10個(gè)隨機(jī)數(shù)

Stream<Integer> result = Stream.generate(random::nextInt).limit(10);

// 直接傳入lambda表達(dá)式

// 下面語(yǔ)句創(chuàng)建的result包含10個(gè)元素寿冕,每個(gè)值由根據(jù)當(dāng)前時(shí)間 % 100計(jì)算得來(lái)

// 以某次執(zhí)行為例,result包含36,3,40,71,46,43,68,97,38,92

result = Stream.generate(() -> (int) (System.nanoTime() % 100)).limit(10);

7) 通過(guò)iterate創(chuàng)建Stream

// 以0為種子椒袍,f(n) = n + 3, f(f(n)) ...

// 下面語(yǔ)句創(chuàng)建的Stream內(nèi)容:0 3 6 9 12 15 18 21 24 27

Stream.iterate(0, n -> n + 3).limit(10).forEach(Stubs::doWhatever);

8) 通過(guò)區(qū)間創(chuàng)建整數(shù)序列Stream

// 通過(guò)range驼唱、rangeClosed生成序列,該序列為數(shù)學(xué)中的區(qū)間序列驹暑。

// 生成[-100, 100)區(qū)間的元素序列玫恳,不包括end元素100

final IntStream range = IntStream.range(-100, 100);

// 由于start > end,不符合區(qū)間定義优俘,返回空區(qū)間京办,Stream中元素長(zhǎng)度為0

final IntStream emptyRange = IntStream.range(100, -100);

// 生成[-100,100]區(qū)間的元素序列,包含end元素100

final IntStream rangeClosed = IntStream.rangeClosed(-100, 100);

// LongStream range生成

// 生成[-100, 100)區(qū)間的元素序列帆焕,不包括end元素100

final LongStream longRange = LongStream.range(-100L, 100L);

// 生成[-100,100]區(qū)間的元素序列惭婿,包含end元素100

final LongStream longRangeClosed = LongStream.rangeClosed(-100L, 100L);

(1)Stream基礎(chǔ)操作

1) 計(jì)算Stream大小

// 計(jì)算Stream中元素的格式,count為特殊的reduce操作叶雹,對(duì)于sum(), max(), min(), average()财饥,count()等操作不建議直接使用reduce()

// 等同于stream.mapToLong(e -> 1L).sum();

long count = Stream.of().count(); // count = 0

count = Stream.of(10).count(); // count = 1

count = Stream.of(10, 20, 30, 40, 50).count(); // count = 5

1) Stream轉(zhuǎn)換為字符串

final Stream<String> stream = Stream.of("red", "blue", "green");

// 執(zhí)行結(jié)果:colors值為red|blue|green

String colors = stream.collect(Collectors.joining("|"));

2) Stream轉(zhuǎn)換為數(shù)組

final Stream<String> stream = Stream.of("red", "blue", "green");

// 執(zhí)行結(jié)果:colors數(shù)組為[red, blue, green]

String[] colors = stream.toArray(String[]::new);

3) Stream轉(zhuǎn)換為ArrayList

final Stream<String> stream = Stream.of("red", "blue", "green");

// colors類(lèi)型為ArrayList,結(jié)果為[red, blue, green]

List<String> colors = stream.collect(Collectors.toList());

4) Stream轉(zhuǎn)換為L(zhǎng)ist

不同業(yè)務(wù)場(chǎng)景對(duì)性能浑娜、內(nèi)存占用等有不同的訴求佑力。對(duì)于ArrayList不滿足的場(chǎng)景,可將Stream元素收集到指定類(lèi)型的List筋遭,如:LinkedList打颤。

final Stream<String> stream = Stream.of("red", "blue", "green");

// Stream轉(zhuǎn)換的List類(lèi)型為L(zhǎng)inkedList

// 執(zhí)行結(jié)果:colors結(jié)果為[red, blue, green]

List<String> colors = stream.collect(Collectors.toCollection(LinkedList::new));

5) Stream轉(zhuǎn)換為指定類(lèi)型Collection

final Stream<String> stream = Stream.of("red", "blue", "green");

// colors為L(zhǎng)inkedHashSet,對(duì)于其他的類(lèi)型在toCollection()方法參數(shù)中指定

Set<String> colors = stream.collect(Collectors.toCollection(LinkedHashSet::new));

6) Stream轉(zhuǎn)換為Set

final Stream<String> stream = Stream.of("red", "blue", "green");

// 默認(rèn)轉(zhuǎn)換為HashSet

// 執(zhí)行結(jié)果:colors值為[red, green, blue]

final Set<String> colors = stream.collect(Collectors.toSet());

7) Stream轉(zhuǎn)換為Map

Collectors.toMap()需要保證Key唯一性漓滔,如果不唯一编饺,則需給出合并策略

Collectors.toMap()需要保證Stream元素為NonNull,且映射到Map的value值必須為NonNull

final Stream<User> stream = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 以User的ID作為key响驴,User實(shí)例作為value透且,轉(zhuǎn)換過(guò)程默認(rèn)使用的是HashMap

// user.getId()必須是唯一的,否則會(huì)拋出java.lang.IllegalStateException: Duplicate key

// 執(zhí)行結(jié)果:map值為

// {1=User(id=1, username=Jerry, salary=0, gender=Male), 2=User(id=2, username=Kitty, salary=0, gender=Female)}

Map<String, User> map = stream.collect(Collectors.toMap(User::getId, Function.identity()));

final Stream<User> stream2 = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 將User的ID作為key,username作為value

// 執(zhí)行結(jié)果:mapIdName值為{1=Jerry, 2=Kitty}

Map<String, String> mapIdName = stream2.collect(Collectors.toMap(User::getId, User::getUsername));

如果Collectors.toMap() key值不唯一秽誊,給出合并策略

final Stream<User> duplicateKeyStream =

? ? Stream.of(new User("1", "Jerry", "Male"), new User("20", "Jerry", "Female"));

// 下面以u(píng)sername作為key鲸沮,Stream中存在同名的username "Jerry"。

// 以“后者覆蓋前者”的策略解決沖突

// 執(zhí)行結(jié)果:map值為{Jerry=User(id=20, username=Jerry, salary=0, gender=Female)}

Map<String, User> map =

? ? duplicateKeyStream.collect(Collectors.toMap(User::getUsername, Function.identity(), (key1, key2) -> key2));

如果Stream存在null元素锅论,Collectors.toMap()轉(zhuǎn)換失敗,建議通過(guò)filter()過(guò)濾后再進(jìn)行轉(zhuǎn)換

final Stream<User> nullElementStream = Stream.of(new User("1", "Jerry", "Male"), null);

// 下面代碼Stream中存在null元素讼溺,Collectors.toMap()將拋出NullPointerException異常

Map<String, String> mapIdName = nullElementStream.collect(Collectors.toMap(User::getId, User::getUsername));

// 過(guò)濾出NonNull的元素后進(jìn)行Map轉(zhuǎn)換,轉(zhuǎn)換后的結(jié)果為{1=Jerry}

nullElementStream.filter(Objects::nonNull).collect(Collectors.toMap(User::getId, User::getUsername));

如果Map的value值為null最易,Collectors.toMap()轉(zhuǎn)換失敗,建議通過(guò)filter()過(guò)濾后再進(jìn)行轉(zhuǎn)換

final Stream<User> nullValueStream = Stream.of(new User("1", "Jerry", "Male"), new User("2", null));

// 將id怒坯、username信息轉(zhuǎn)換為map,由于存在username為null藻懒,Collectors.toMap()將拋出NullPointerException異常

Map<String, String> mapIdName = nullValueStream.collect(Collectors.toMap(User::getId, User::getUsername));

// 過(guò)濾出Map的value為NonNull的元素后進(jìn)行Map轉(zhuǎn)換剔猿,轉(zhuǎn)換后的結(jié)果為{1=Jerry}

nullValueStream.filter(p -> p != null && StringUtils.isNotEmpty(p.getUsername()))

? ? .collect(Collectors.toMap(User::getId, User::getUsername));

8) Stream轉(zhuǎn)換為分組Map

final Stream<User> stream = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 按性別分組,分組結(jié)果為

// {Female=[User(id=2, username=Kitty, salary=0, gender=Female)], Male=[User(id=1, username=Jerry, salary=0,

// gender=Male)]}

Map<String, List<User>> group = stream.collect(Collectors.groupingBy(User::getGender));

// Stream實(shí)例執(zhí)行一次終端操作后將不能再次使用嬉荆,因此归敬,此處創(chuàng)建新的Stream

final Stream<User> stream2 = Stream.of(new User("1", "Jerry", "Male"), new User("2", "Kitty", "Female"));

// 按是否為Female分組,分組結(jié)果為

// {false=[User(id=1, username=Jerry, salary=0, gender=Male)], true=[User(id=2, username=Kitty, salary=0,

// gender=Female)]}

Map<Boolean, List<User>> group2 =

? ? stream2.collect(Collectors.partitioningBy(p -> "Female".equalsIgnoreCase(p.getGender())));

? ? 4.日期時(shí)間 API

? ? ? ? java.time包涵蓋了所有處理日期鄙早,時(shí)間弄慰,日期/時(shí)間,時(shí)區(qū)蝶锋,時(shí)刻(instants)陆爽,過(guò)程(during)與時(shí)鐘(clock)的操作

? ? ? ? import java.time.LocalDate;

? ? ? ? import java.time.LocalTime;

? ? ? ? import java.time.LocalDateTime;

? ? ? ? import java.time.Month;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市扳缕,隨后出現(xiàn)的幾起案子慌闭,更是在濱河造成了極大的恐慌,老刑警劉巖躯舔,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驴剔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡粥庄,警方通過(guò)查閱死者的電腦和手機(jī)丧失,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)惜互,“玉大人布讹,你說(shuō)我怎么就攤上這事⊙刀眩” “怎么了描验?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)坑鱼。 經(jīng)常有香客問(wèn)我膘流,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任呼股,我火速辦了婚禮耕魄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘彭谁。我一直安慰自己屎开,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布马靠。 她就那樣靜靜地躺著,像睡著了一般蔼两。 火紅的嫁衣襯著肌膚如雪甩鳄。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天额划,我揣著相機(jī)與錄音妙啃,去河邊找鬼。 笑死俊戳,一個(gè)胖子當(dāng)著我的面吹牛揖赴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抑胎,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼燥滑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了阿逃?” 一聲冷哼從身側(cè)響起铭拧,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恃锉,沒(méi)想到半個(gè)月后搀菩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡破托,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年肪跋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片土砂。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡州既,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出萝映,到底是詐尸還是另有隱情易桃,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布锌俱,位于F島的核電站晤郑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜造寝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一磕洪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诫龙,春花似錦析显、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至锦聊,卻和暖如春歹嘹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孔庭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工尺上, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人圆到。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓怎抛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親芽淡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子马绝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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

  • Java 8自Java 5(發(fā)行于2004)以來(lái)最具革命性的版本。Java 8 為Java語(yǔ)言挣菲、編譯器迹淌、類(lèi)庫(kù)、開(kāi)發(fā)...
    huoyl0410閱讀 637評(píng)論 1 2
  • Java 8自Java 5(發(fā)行于2004)以來(lái)最具革命性的版本己单。Java 8 為Java語(yǔ)言唉窃、編譯器、類(lèi)庫(kù)纹笼、開(kāi)發(fā)...
    誰(shuí)在烽煙彼岸閱讀 891評(píng)論 0 4
  • 目錄結(jié)構(gòu) 介紹 Java語(yǔ)言的新特性2.1 Lambdas表達(dá)式與Functional接口2.2 接口的默認(rèn)與靜態(tài)...
    夜風(fēng)月圓閱讀 477評(píng)論 0 2
  • Java 8 中的 Stream 是對(duì)集合(Collection)對(duì)象功能的增強(qiáng)纹份,它專(zhuān)注于對(duì)集合對(duì)象進(jìn)行各種非常便...
    寫(xiě)代碼的杰西閱讀 496評(píng)論 0 0
  • 一.函數(shù)式接口 函數(shù)式接口,就是一個(gè)接口里面只有一個(gè)接口廷痘,接口上都用@FunctionalInterface注釋修...
    豪大大大閱讀 386評(píng)論 0 0