成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java8-流

whinc / 1810人閱讀

摘要:因此,使用并行流需要考慮以下幾點(diǎn)數(shù)據(jù)量將問題分解之后并行化處理,再將結(jié)果合并會(huì)帶來額外的開銷。

目錄

簡介

用法

例子

注意點(diǎn)

一. 簡介

流是Java8引入的一個(gè)新特性,提供了對集合元素一系列便捷的操作,可以用很少的代碼實(shí)現(xiàn)復(fù)雜的功能。
流有兩大類,分別是對象流(Stream),基本數(shù)據(jù)流(IntStream、LongStream、DoubleStream)。

二.用法

流的使用通常為三個(gè)步驟:①創(chuàng)建流 ②描述流 ③求值

創(chuàng)建流

通過Stream靜態(tài)工廠方法來創(chuàng)建,Stream類提供了以下方法創(chuàng)建流。

of:
Stream stream = Stream.of(1, 2, 3, 4);
IntStream intStream = IntStream.of(new int[]{1, 2, 3});

generator:生成一個(gè)無限長度的Stream
可以看作是個(gè)工廠,每次返回一個(gè)給定類型的對象。
Stream generate = Stream.generate(Math::random);

iterate:生成無限長度的Stream
其元素的生成是重復(fù)對給定的種子值(seed)調(diào)用用戶指定函數(shù)生成的
Stream stream = Stream.iterate(1, element -> element + 1);

empty():生成空流
Stream.empty();

通過文件生成流:File.lines()
Stream lines = Files.lines(Paths.get("data.txt"));

最常用的 通過Collection子類獲取Stream
List list = new ArrayList<>();
Stream stream = list.stream();

通過Arrays.stream()封裝數(shù)據(jù)生成流,也很常用
IntStream intStream = Arrays.stream(new int[]{1, 2, 3});

比較少用的 CharSequence 接口方法 .chars()
String str = "hello world";
IntStream intStream = str.chars();

描述流

創(chuàng)建好流之后,就可以描述流了。更準(zhǔn)確的說法是,聲明流的中間操作。
中間操作比較常用的有以下幾種(返回值為Stream的均為中間操作)

.filter(man -> man.getAge() > 18)  過濾器

.map(Man::getName)       獲取字段,map操作可以執(zhí)行多次,將數(shù)據(jù)轉(zhuǎn)為我們期望的

.mapToInt            轉(zhuǎn)為數(shù)值流,這個(gè)和sum這些組合使用可以省去裝箱成本

.limit(3)            截?cái)嗔?,前三個(gè)

.distinct()            去重

.sorted()            排序

.skip(3)             丟棄前三個(gè)

.flatMap(Arrays::stream)     合并流

求值

與中間操作相對應(yīng)的是終端操作,也就是我們的第三步,求值。
常用的終端操作有以下幾種(返回值不為Stream的為終端操作)

.collect(toList());    結(jié)果轉(zhuǎn)為List格式

.collect(toSet());    結(jié)構(gòu)轉(zhuǎn)為Set格式,自帶distinct效果

.count();       計(jì)數(shù)

.findfirst();       找第一個(gè)

.findAny();      找任何一個(gè)

.forEach(System.out::println) 為每個(gè)元素進(jìn)行的操作

.min         獲取最小值

.max         獲取最大值

說明
流是使用了內(nèi)部迭代而不是外部迭代
內(nèi)部迭代使用了惰性求值,只有在需要結(jié)果的那一刻才進(jìn)行求值。
所有的中間操作(只描述流)都是惰性求值,因?yàn)橹环祷亓薙tream。
三.例子

// 用戶類

public class User {
    private Integer id;
    private String name;
    private Integer age;
    // GET SET Constructor ..
}

// 初始化數(shù)據(jù)

List userList = new ArrayList() {
    /** */
    private static final long serialVersionUID = 1L;
    {
        add(new User(1, "Luffy",   17)); 
?       add(new User(2, "Zoro",    19)); 
        add(new User(3, "Nami",    18)); 
        add(new User(4, "Usopp",   17)); 
        add(new User(5, "Sanji",   19)); 
        add(new User(6, "Chopper", 15));
        add(new User(7, "Robin",   28)); 
        add(new User(8, "FRANKY",  34)); 
        add(new User(9, "BROOK",   88)); 
    }
};

// 例子

@Test
public void test1() {
    // 獲取所有年齡大于17的用戶
    List users = userList.stream()
            .filter(user -> user.getAge() > 17)
            .collect(Collectors.toList());
    System.out.println(users);
}

// 靜態(tài)導(dǎo)入Collectors后會(huì)更簡潔。
// import static java.util.stream.Collectors.*;

@Test
public void test2() {
    // 根據(jù)年齡是否大于17歲對集合進(jìn)行分塊
    Map> users = userList.stream()
        .collect(partitioningBy(u -> u.getAge() > 17));
    System.out.println(users);
}

@Test
public void test3() {
    // 按照年齡,將用戶分組
    Map> users = userList.stream()
        .collect(groupingBy(User::getAge));
    System.out.println(users);
}

@Test
public void test4() {
    // 獲取所有用戶的名稱
    List names = userList.stream()
        .map(User::getName)
        .collect(toList());
    System.out.println(names);
}

@Test
public void test5() {
    // 獲取年齡最大的用戶(只返回一個(gè))
    User user = userList.stream()
        .max((u1, u2) -> {
            return u1.getAge() > u2.getAge() ? 1 : -1;
        })
        .get();
    System.out.println(user);
}

@Test
public void test6() {
    // 獲取用戶年齡總和
    int ageSum = userList.stream()
        .map(User::getAge)
        .reduce(0, (acc, element) -> {
            acc += element;
            return acc;
        });
    System.out.println(ageSum);

    ageSum = userList.stream()
        .map(User::getAge)
        .reduce(0, Integer::sum);
    System.out.println(ageSum);

    ageSum = userList.stream()
        .collect(summingInt(User::getAge));
    System.out.println(ageSum);
}

@Test
public void test7() {
    // 獲取組成用戶姓名的字母
    Set set = userList.stream()
        .map(User::getName)
        .map(name -> name.split(""))
        .flatMap(Arrays::stream)
        .collect(toSet());
    System.out.println(set);
}
四.注意點(diǎn)

如何進(jìn)行調(diào)試

// 可以利用peek查看流中的數(shù)據(jù)狀態(tài)
userList.stream()
    .peek(System.out::println)
    .map(u -> u.getName())
    .peek(System.out::println)
    .collect(toList());

使用并行還是串行

// 將流改為并行流十分簡單,只需要將stream方法改為parallelStream
Map> users = userList.parallelStream()                
    .collect(groupingBy(User::getAge));

// 或是使用 parallel() 聲明為并行
Stream.iterate(0L, i -> i + 1)
    .parallel()
    .limit(10)
    .reduce(0L, Long::sum);

Java8流的并行屬于數(shù)據(jù)并行,即將數(shù)據(jù)分為幾部分,利用多核CPU對每塊數(shù)據(jù)執(zhí)行運(yùn)算,最終匯總數(shù)據(jù),得到答案。底層是使用了fork/join框架,fork遞歸分解問題,然后每段并行執(zhí)行,最終join合并結(jié)果。?因此,使用并行流需要考慮以下幾點(diǎn):

數(shù)據(jù)量 : 將問題分解之后并行化處理,再將結(jié)果合并會(huì)帶來額外的開銷。
因此數(shù)據(jù)足夠大,每個(gè)數(shù)據(jù)處理管道花費(fèi)的時(shí)間足夠多時(shí),并行化處理才有意義

將數(shù)據(jù)對半分解的難易程度 :
ArrayList、數(shù)組、IntStream.range,這些數(shù)據(jù)結(jié)構(gòu)支持隨機(jī)讀取,也就是說能輕而易舉地被任意分解。
LinkedList,對半分解太難。需要o(n) 時(shí)間復(fù)雜度

核的數(shù)量 : 單核的機(jī)器是沒必要并行化的

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68998.html

相關(guān)文章

  • Java8實(shí)戰(zhàn)》-讀書筆記第一章(02)

    摘要:實(shí)戰(zhàn)讀書筆記第一章從方法傳遞到接著上次的,繼續(xù)來了解一下,如果繼續(xù)簡化代碼。去掉并且生成的數(shù)字是萬,所消耗的時(shí)間循序流并行流至于為什么有時(shí)候并行流效率比循序流還低,這個(gè)以后的文章會(huì)解釋。 《Java8實(shí)戰(zhàn)》-讀書筆記第一章(02) 從方法傳遞到Lambda 接著上次的Predicate,繼續(xù)來了解一下,如果繼續(xù)簡化代碼。 把方法作為值來傳遞雖然很有用,但是要是有很多類似與isHeavy...

    lushan 評論0 收藏0
  • 樂字節(jié)-Java8新特性之Stream(上)

    摘要:需要注意的是很多流操作本身就會(huì)返回一個(gè)流,所以多個(gè)操作可以直接連接起來,如下圖這樣,操作可以進(jìn)行鏈?zhǔn)秸{(diào)用,并且并行流還可以實(shí)現(xiàn)數(shù)據(jù)流并行處理操作。為集合創(chuàng)建并行流。 上一篇文章,小樂給大家介紹了《Java8新特性之方法引用》,下面接下來小樂將會(huì)給大家介紹Java8新特性之Stream,稱之為流,本篇文章為上半部分。 1、什么是流? Java Se中對于流的操作有輸入輸出IO流,而Jav...

    dingda 評論0 收藏0
  • java8系列」式編程Stream

    摘要:前言系列神秘的系列神奇的函數(shù)式接口繼上兩篇之后,本文已經(jīng)系列的第三篇了。相反,他們會(huì)返回一個(gè)持有結(jié)果的新。操作是延遲執(zhí)行的。截?cái)嗔鳎蛊湓夭怀^給定數(shù)量。返回流中元素總數(shù)。返回流中最大值。 前言 「Java8系列」神秘的Lambda「Java8系列」神奇的函數(shù)式接口繼上兩篇之后,本文已經(jīng)java8系列的第三篇了。本篇文章比較長,但我希望大家都能認(rèn)真讀完。讀不完可以先收藏,在找時(shí)間讀。...

    bovenson 評論0 收藏0
  • Java8特性和Lambda表達(dá)式

    摘要:表達(dá)式體現(xiàn)了函數(shù)式編程的思想,即一個(gè)函數(shù)亦可以作為另一個(gè)函數(shù)參數(shù)和返回值,使用了函數(shù)作參數(shù)返回值的函數(shù)被稱為高階函數(shù)。對流對象進(jìn)行及早求值,返回值不在是一個(gè)對象。 Java8主要的改變是為集合框架增加了流的概念,提高了集合的抽象層次。相比于舊有框架直接操作數(shù)據(jù)的內(nèi)部處理方式,流+高階函數(shù)的外部處理方式對數(shù)據(jù)封裝更好。同時(shí)流的概念使得對并發(fā)編程支持更強(qiáng)。 在語法上Java8提供了Lamb...

    gaara 評論0 收藏0
  • Stream與Lambda表達(dá)式(一) 雜談

    摘要:一流轉(zhuǎn)換為數(shù)組集合陳楊將流轉(zhuǎn)換為數(shù)組將流轉(zhuǎn)換為數(shù)組將流轉(zhuǎn)換為集合將流轉(zhuǎn)換為集合解析 一、流 轉(zhuǎn)換為數(shù)組、集合 package com.java.design.java8.Stream; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context...

    Harpsichord1207 評論0 收藏0
  • Java8(stream)操作

    摘要:串行與并行可以分為串行與并行兩種,串行流和并行流差別就是單線程和多線程的執(zhí)行。返回串行流返回并行流和方法返回的都是類型的對象,說明它們在功能的使用上是沒差別的。唯一的差別就是單線程和多線程的執(zhí)行。 Stream是什么 Stream是Java8中新加入的api,更準(zhǔn)確的說: Java 8 中的 Stream 是對集合(Collection)對象功能的增強(qiáng),它專注于對集合對象進(jìn)行各種非常便...

    yacheng 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<