亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么從零開始學習Java8 Stream

發布時間:2021-10-21 16:14:35 來源:億速云 閱讀:99 作者:iii 欄目:編程語言

這篇文章主要講解了“怎么從零開始學習Java8 Stream”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么從零開始學習Java8 Stream”吧!

為何需要引入流

在我們平常的開發中幾乎每天都會有到List、Map等集合API,若是問Java什么API使用最多,我想也應該是集合了。舉例:假如我有個集合List,里面元素有1,7,3,8,2,4,9,需要找出里面大于5的元素,具體實現代碼:

public List<integer> getGt5Data() {
    List<integer> data = Arrays.asList(1, 7, 3, 8, 2, 4, 9);
    List<integer> result = new ArrayList&lt;&gt;();
    for (Integer num : data) {
        if (num &gt; 5) {
            result.add(num);
        }
    }
    return result;
}

這個實現讓我們感覺到了集合的操作不是太完美,如果是數據庫的話,我們只需要簡單的在where后面加一個條件大于5就可以得到我們想要的結果,為什么Java的集合就沒有這種API呢? 其次,如果我們遇到有大集合需要處理,為了提高性能,我們可能需要使用到多線程來處理,但是寫并行程序的復雜度有提高了不少。

基于以上的問題,所有Java8推出了Stream


Stream簡介

Stream有哪些特點:

  • 元素的序列:與集合一樣可以訪問里面的元素,集合講的是數據,而流講的是操作,比如:filter、map

  • 源: 流也需要又一個提供數據的源,順序和生成時的順序一致

  • 數據的操作:流支持類似于數據庫的操作,支持順序或者并行處理數據;上面的例子用流來實現會更加的簡潔

public List<integer> getGt5Data() {
    return Stream.of(1, 7, 3, 8, 2, 4, 9)
            .filter(num -&gt; num &gt; 5)
            .collect(toList());
}
  • 流水線操作:很多流的方法本身也會返回一個流,這樣可以把多個操作連接起來,形成流水線操作

  • 內部迭代:與以往的迭代不同,流使用的內部迭代,用戶只需要專注于數據處理

  • 只能遍歷一次: 遍歷完成之后我們的流就已經消費完了,再次遍歷的話會拋出異常


使用Stream

Java8中的Stream定義了很多方法,基本可以把他們分為兩類:中間操作、終端操作;要使用一個流一般都需要三個操作:

  1. 定義一個數據源

  2. 定義中間操作形成流水線

  3. 定義終端操作,執行流水線,生成計算結果

構建流
  1. 使用Stream.of方法構建一個流

Stream.of("silently","9527","silently9527.cn")
        .forEach(System.out::println);
  1. 使用數組構建一個流

int[] nums = {3, 5, 2, 7, 8, 9};
Arrays.stream(nums).sorted().forEach(System.out::println);
  1. 通過文件構建一個流 使用java.nio.file.Files.lines方法可以輕松構建一個流對象

Files.lines(Paths.get("/Users/huaan9527/Desktop/data.txt"))
                .forEach(System.out::println);
中間操作

中間操作會返回另外一個流,這樣可以讓多個操作連接起來形成一個流水線的操作,只要不觸發終端操作,那么這個中間操作都不會實際執行。

filter

該操作接受一個返回boolean的函數,當返回false的元素將會被排除掉

舉例:假如我們100個客戶,需要篩選出年齡大于20歲的客戶

List<customer> matchCustomers = allCustomers.stream()
                .filter(customer -&gt; customer.getAge()&gt;20)
                .collect(toList());
distinct

該操作將會排除掉重復的元素

List<integer> data = Stream.of(1, 7, 3, 8, 2, 4, 9, 7, 9)
        .filter(num -&gt; num &gt; 5)
        .distinct()
        .collect(toList());
limit

該方法限制流只返回指定個數的元素

List<integer> data = Stream.of(1, 7, 3, 8, 2, 4, 9, 7, 9)
        .filter(num -&gt; num &gt; 5)
        .limit(2)
        .collect(toList());
skip

扔掉前指定個數的元素;配合limit使用可以達到翻頁的效果

List<integer> data = Stream.of(1, 7, 3, 8, 2, 4, 9, 7, 9)
        .filter(num -&gt; num &gt; 5)
        .skip(1)
        .limit(2)
        .collect(toList());
map

該方法提供一個函數,流中的每個元素都會應用到這個函數上,返回的結果將形成新類型的流繼續后續操作。 舉例:假如我們100個客戶,需要篩選出年齡大于20歲的客戶,打印出他們的名字

allCustomers.stream()
            .filter(customer -&gt; customer.getAge() &gt; 20)
            .map(Customer::getName)
            .forEach(System.out::println);

在調用map之前流的類型是Stream<customer>,執行完map之后的類型是Stream<string>

flatMap

假如我們需要把客戶的名字中的每個字符打印出來,代碼如下:

List<customer> allCustomers = Arrays.asList(new Customer("silently9527", 30));
allCustomers.stream()
        .filter(customer -&gt; customer.getAge() &gt; 20)
        .map(customer -&gt; customer.getName().split(""))
        .forEach(System.out::println);

執行本次結果,你會發現沒有達到期望的結果,打印的結果

[Ljava.lang.String;@38cccef

這是因為調用map之后返回的流類型是Stream<string[]>,所有forEach的輸入就是String[];這時候我們需要使用flatMap把String[]中的每個元素都轉換成一個流,然后在把所有的流連接成一個流,修改后的代碼如下

List<customer> allCustomers = Arrays.asList(new Customer("silently9527", 30));
allCustomers.stream()
        .filter(customer -&gt; customer.getAge() &gt; 20)
        .map(customer -&gt; customer.getName().split(""))
        .flatMap(Arrays::stream)
        .forEach(System.out::println);

執行結果:

怎么從零開始學習Java8 Stream

sorted

對所有的元素進行排序

List<integer> numbers = Arrays.asList(1, 7, 3, 8, 2, 4, 9);
numbers.stream().sorted(Integer::compareTo).forEach(System.out::println);
終端操作

終端操作會執行所有的中間操作生成執行的結果,執行的結果不在是一個流。

anyMatch

如果流中有一個元素滿足條件將返回true

if (allCustomers.stream().anyMatch(customer -&gt; "silently9527".equals(customer.getName()))) {
    System.out.println("存在用戶silently9527");
}
allMatch

確保流中所有的元素都能滿足

if (allCustomers.stream().allMatch(customer -&gt; customer.getAge() &gt; 20)) {
    System.out.println("所有用戶年齡都大于20");
}
noneMatch

與allMatch操作相反,確保流中所有的元素都不滿足

if (allCustomers.stream().noneMatch(customer -&gt; customer.getAge() &lt; 20)) {
    System.out.println("所有用戶年齡都大于20");
}
findAny

返回流中的任意一個元素,比如返回大于20歲的任意一個客戶

Optional<customer> optional = allCustomers.stream()
        .filter(customer -&gt; customer.getAge() &gt; 20)
        .findAny();
findFirst

返回流中的第一個元素

Optional<customer> optional = allCustomers.stream()
        .filter(customer -&gt; customer.getAge() &gt; 20)
        .findFirst();
reduce

接受兩個參數:一個初始值,一個BinaryOperator<t> accumulator將兩個元素合并成一個新的值 比如我們對一個數字list累加

List<integer> numbers = Arrays.asList(1, 7, 3, 8, 2, 4, 9);
Integer sum = numbers.stream().reduce(0, (a, b) -&gt; a + b);

上面的代碼,我們可以簡寫

Integer reduce = numbers.stream().reduce(0, Integer::sum);

找出流中的最大值、最小值 min、max

numbers.stream().reduce(Integer::max)
numbers.stream().reduce(Integer::min)
count

統計流中元素的個數

numbers.stream().count()

數據收集器collect

在Java8中已經預定義了很多收集器,我們可以直接使用,所有的收集器都定義在了Collectors中,基本上可以把這些方法分為三類:

  • 將元素歸約和匯總成一個值

  • 分組

  • 分區

歸約和匯總

先看下我們之前求最大值和最小值采用收集器如何實現

  1. 找出年齡最大和最小的客戶

Optional<customer> minAgeCustomer = allCustomers.stream().collect(minBy(Comparator.comparing(Customer::getAge)));
Optional<customer> maxAgeCustomer = allCustomers.stream().collect(maxBy(Comparator.comparing(Customer::getAge)));
  1. 求取年齡的平均值

Double avgAge = allCustomers.stream().collect(averagingInt(Customer::getAge));
  1. 進行字符串的連接

把客戶所有人的名字連接成一個字符串用逗號分隔

allCustomers.stream().map(Customer::getName).collect(joining(","));
分組

在數據庫的操作中,我們可以輕松的實現通過一個屬性或者多個屬性進行數據分組,接下來我們看看Java8如何來實現這個功能。

  1. 根據客戶的年齡進行分組

Map<integer, list<customer>&gt; groupByAge = allCustomers.stream().collect(groupingBy(Customer::getAge));

Map的key就是分組的值年齡,List<customer>就是相同年齡的用戶

  1. 我們需要先按照用戶的地區分組,在按年齡分組

Map<string, map<integer, list<customer>&gt;&gt; groups = allCustomers.stream()
                .collect(groupingBy(Customer::getArea, groupingBy(Customer::getAge)));

在相對于普通的分組,這里多傳了第二個參數又是一個groupingBy;理論上我們可以通過這個方式擴展到n層分組

  1. 分組后再統計數量

Map<string, long> groupByCounting = allCustomers.stream()
            .collect(groupingBy(Customer::getArea, counting()));
  1. 以用戶所在地區分組后找出年齡最大的用戶

Map<string, optional<customer>&gt; optionalMap = allCustomers.stream()
                .collect(groupingBy(Customer::getArea, maxBy(Comparator.comparing(Customer::getAge))));

這時候返回的Map中的value被Optional包裹,如果我們需要去掉Optional,可以使用collectingAndThen

Map<string, customer> customerMap = allCustomers.stream()
        .collect(groupingBy(Customer::getArea,
                collectingAndThen(maxBy(Comparator.comparing(Customer::getAge)), Optional::get)
        ));

感謝各位的閱讀,以上就是“怎么從零開始學習Java8 Stream”的內容了,經過本文的學習后,相信大家對怎么從零開始學習Java8 Stream這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

澄城县| 瑞昌市| 舒兰市| 家居| 辉南县| 闽侯县| 婺源县| 西宁市| 邛崃市| 麦盖提县| 贵阳市| 康平县| 彭阳县| 德州市| 新津县| 彭州市| 抚顺市| 扶风县| 浦东新区| 高雄县| 泗水县| 万山特区| 沂水县| 卢氏县| 襄汾县| 确山县| 沙湾县| 武鸣县| 新巴尔虎右旗| 彩票| 镇沅| 永靖县| 诸城市| 河西区| 定兴县| 花垣县| 秦安县| 怀仁县| 旺苍县| 贺州市| 靖西县|