国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Java8 函數(shù)式編程stream流

這篇具有很好參考價(jià)值的文章主要介紹了Java8 函數(shù)式編程stream流。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

開篇介紹

Java 8 中新增的特性旨在幫助程序員寫出更好的代碼,其中對核心類庫的改進(jìn)是很關(guān)鍵的一部分,也是本章的主要內(nèi)容。對核心類庫的改進(jìn)主要包括集合類的 API 和新引入的流(Stream),流使程序員得以站在更高的抽象層次上對集合進(jìn)行操作。下面將介紹stream流的用法。

1.初始環(huán)境準(zhǔn)備

? 場景:現(xiàn)在有一個(gè)公司,公司部門有一級部門,二級部門甲和二級部門乙(其中二級部門甲和二級部門乙是一級部門的子部門),

一級部門下面有有001號員工小明,二級部門甲下面有002號員工小剛和003號員工小李,二級部門乙有002號員工小剛和004號員工小張,其中員工id是唯一的,員工小剛既是二級部門甲又是二級部門乙的員工。代碼展示如下:

public class LambdaUseCase {
    static List<Department> departmentList;
    static {
        // 一級部門,部門人員有001號員工小明
        Department departmentOne = new Department("一級部門", 1,10000L,11000L,
                Arrays.asList(new Person("001","小明",22)));
        // 二級部門甲,部門人員有002號員工小剛和003號員工小李
        Department departmentTwoFirst = new Department("二級部門甲", 2,8000L,13000L,
                Arrays.asList(new Person("002","小剛",23),
                        new Person("003","小李",32)));
        // 二級部門乙,部門人員有002號員工小剛和004號員工小張
        Department departmentTwoSecond = new Department("二級部門已", 2,7500L,15000L,
                Arrays.asList(new Person("002","小剛",23),
                        new Person("004","小張",34)));

        departmentList = Arrays.asList(departmentOne,departmentTwoFirst,departmentTwoSecond);
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Department {
    // 部門名
    private String departmentName;
    // 部門等級
    private Integer departmenRank;
    // 部門薪資(單位分)
    private Long departSalary;
    // 部門日盈利
    private Long departProfit;
    // 部門人員集合
    private List<Person> persons;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
//重寫equal和hashcode方法,用于數(shù)據(jù)去重
@EqualsAndHashCode
class Person {
    // 人員id
    private String personId;
    // 人員姓名
    private String personName;
    // 人員年齡
    private Integer personAge;
}

2.創(chuàng)建流

單列集合: 集合對象.stream() 創(chuàng)建流

departmentList.stream();

數(shù)組:Arrays.stream(數(shù)組) 或者使用Stream.of來創(chuàng)建

Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(arr);
Stream<Integer> stream2 = Stream.of(arr);
Stream.of(1,2,3,4);

雙列集合:轉(zhuǎn)換成單列集合后再創(chuàng)建

Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();

3.中間操作

3.1 map

如果有一個(gè)函數(shù)可以將一種類型的值轉(zhuǎn)換成另外一種類型,map 操作就可以使用該函數(shù),將一個(gè)流中的值轉(zhuǎn)換成一個(gè)新的流

需求:公司今年收益提供,決定把所有部門的平均薪資提升1000。

List<Department> departments = departmentList.stream().map(e -> {
    e.setDepartSalary(e.getDepartSalary() + 1000);
    return e;
}).collect(Collectors.toList());

3.2 filter

對流中的元素進(jìn)行過濾,篩選出符合過濾條件的數(shù)據(jù)

需求:需要篩選出部門平均薪資大于等于8000的數(shù)據(jù)。

List<Department> departments = departmentList.stream()
		.filter(e -> e.getDepartSalary() >= 8000)
		.collect(Collectors.toList());

3.3 flatMap

flatMap 方法可用 Stream 替換值,然后將多個(gè) Stream 連接成一個(gè) Stream

需求:把公司所有的人員收集到一個(gè)集合中。

不使用flatMap,你可能會這么做,循環(huán)里套循環(huán),看上去不太美觀。

Set<Person> personSet = new HashSet<>();
departmentList.stream().forEach(e->{
	e.getPersons().stream().forEach(person->{
		personSet.add(person);
	});
});

使用flatMap寫法。

Set<Person> personSet = departmentList.stream()
        .flatMap(e -> e.getPersons().stream())
        .collect(Collectors.toSet());

3.4 distinct

去除流中的重復(fù)元素

需求:將公司所有的人員統(tǒng)計(jì)出來,這回不使用Set去重,注意:002號員工即在二級部門甲又在二級部門乙

List<Person> personSet = departmentList.stream()
        .flatMap(e -> e.getPersons().stream())
        .distinct()
        .collect(Collectors.toList());

注意:distinct方法是依賴Object的equals方法來判斷是否是相同對象的。所以需要注意重寫equals方法。

3.5 sorted

對流中的元素進(jìn)行排序

需求: 按薪資從低到高將部門列出來。

List<Department> departments = departmentList.stream()
        .sorted((o1, o2) -> o1.getDepartSalary().compareTo(o2.getDepartSalary()))
        .collect(Collectors.toList());

注意:如果調(diào)用空參的sorted()方法,需要流中的元素是實(shí)現(xiàn)了Comparable。

3.6 limit

可以設(shè)置流的最大長度,超出的部分將被拋棄

需求:按薪資從低到高將部門列出來,并且找出薪資最低的倆個(gè)部門

List<Department> departments = departmentList.stream()
		.sorted(Comparator.comparing(Department::getDepartSalary))
		.limit(2)
		.collect(Collectors.toList());

3.7 skip

跳過流中的前n個(gè)元素,返回剩下的元素

需求:按薪資從低到高將部門列出來,并且忽略薪資最低的部門

List<Department> departments = departmentList.stream()
		.sorted(Comparator.comparing(Department::getDepartSalary))
		.skip(1)
		.collect(Collectors.toList());

4.終結(jié)操作

4.1 foreach

對流中的元素進(jìn)行遍歷操作

需求:要求輸出全部部門的名稱

departmentList.stream()
                .forEach(e -> System.out.println(e.getDepartmentName()));

4.2 count

可以用來獲取當(dāng)前流中元素的個(gè)數(shù)。

需求:統(tǒng)計(jì)部門的格式

long count = departmentList.stream()
    .count();

4.3 max和min

Stream 上常用的操作之一是求最大值和最小值

需求:分別找出部門里面薪資最高的部門和最低的部門

Department maxDepartment = departmentList.stream()
		.max(Comparator.comparing(Department::getDepartSalary))
		.get();
Department minDepartment = departmentList.stream()
		.min(Comparator.comparing(Department::getDepartSalary))
		.get();

4.4 collect

將當(dāng)前的流轉(zhuǎn)換為一個(gè)集合

4.4.1 Collectors.toList()

需求:獲得一個(gè)保存所有部門名字的集合

List<String> departNameList = departmentList.stream()
		.map(Department::getDepartmentName)
		.collect(Collectors.toList());

4.4.2 Collectors.toSet()

需求:獲得部門所有人的姓名(重名的忽略)

Set<String> personNameList = departmentList.stream()
		.flatMap(e -> e.getPersons().stream())
		.map(Person::getPersonName)
        .collect(Collectors.toSet());

4.4.3 Collectors.toMap(keyMapper, valueMapper)

需求:獲得部門名稱當(dāng)做key,員工當(dāng)做value的Map

Map<String, List<Person>> collect = departmentList.stream()
		.collect(Collectors.toMap(Department::getDepartmentName, Department::getPersons));

4.4.4 Collectors.joining()

需求:將所有的部門名字連起來,并且前綴是【,后綴是】,分隔符是,

departmentList.stream()
		.map(Department::getDepartmentName)
		.collect(Collectors.joining(",","[","]"));

4.4.5 Collectors.partitioningBy(predicate)

接受一個(gè)流,并將其分成兩部分,使用 Predicate 對象判斷一個(gè)元素應(yīng)該屬于哪個(gè)部分,并根據(jù)布爾值返回一個(gè) Map 到列表。

需求:將一級部門和其他級別的部門分離出來

Map<Boolean, List<Department>> collect = departmentList
    .stream()
    .collect(Collectors.partitioningBy(e -> e.getDepartmenRank() == 1));

4.4.6 Collectors.groupingBy(classifier)

接受一個(gè)分類函數(shù),用來對數(shù)據(jù)分組

需求:將部門按部門的階級分組

Map<Integer, List<Department>> collect = departmentList
    .stream()
    .collect(Collectors.groupingBy(Department::getDepartmenRank));

4.4.7 組合收集器

各種收集器已經(jīng)很強(qiáng)大了,但如果將它們組合起來,會變得更強(qiáng)大。

需求:統(tǒng)計(jì)各個(gè)階級部門的平均薪資

Map<Integer, Double> collect = departmentList.stream()
.collect(Collectors.groupingBy(Department::getDepartmenRank,Collectors.averagingLong(Department::getDepartSalary)));

這個(gè)例子中用到了第二個(gè)收集器,用以收集最終結(jié)果的一個(gè)子集。這些收集器叫作下游收集器。收集器是生成最終結(jié)果的一劑配方,下游收集器則是生成部分結(jié)果的配方,主收集器中會用到下游收集器。這種組合使用收集器的方式,使得它們在 Stream 類庫中的作用更加強(qiáng)大。

4.5 reduce

對流中的數(shù)據(jù)按照指定的方式計(jì)算出結(jié)果

需求:計(jì)算出部門總的日盈利

Long sum = departmentList.stream()
		.map(Department::getDepartProfit)
		.reduce(0L, (result, element) -> result + element);

4.6 anyMatch

可以用來判斷是否有任意符合匹配條件的元素,結(jié)果為boolean類型。

需求:判斷部門中有沒有薪資大于9000的部門

boolean b = departmentList.stream()
                .anyMatch(e -> e.getDepartSalary() > 9000L);

4.7 allMatch

可以用來判斷是否都符合匹配條件,結(jié)果為boolean類型。如果都符合結(jié)果為true,否則結(jié)果為false。

需求:判斷部門薪資是不是都大于9000

boolean b = departmentList.stream()
                .allMatch(e -> e.getDepartSalary() > 9000L);

4.8 noneMatch

可以判斷流中的元素是否都不符合匹配條件。如果都不符合結(jié)果為true,否則結(jié)果為false

需求:判斷是不是所有的部門薪資都大于9000

boolean b = departmentList.stream()
                .noneMatch(e -> e.getDepartSalary() <= 9000L);

4.9 findAny

獲取流中的任意一個(gè)元素。該方法沒有辦法保證獲取的一定是流中的第一個(gè)元素。

需求:找到任意一個(gè)部門

Department department = departmentList
                .stream()
                .findAny()
                .get();

4.10 findFirst

獲取流中的第一個(gè)元素。

需求:獲得薪資最低的一個(gè)部門

Department department = departmentList
                .stream()
                .sorted(Comparator.comparing(Department::getDepartSalary))
                .findFirst()
                .get();

5.高級用法

5.1 對基本類型處理(mapToInt,mapToLong,mapToDouble)

在 Java 中,有一些相伴的類型,比如 int 和 Integer——前者是基本類型,后者是裝箱類型。基本類型內(nèi)建在語言和運(yùn)行環(huán)境中,是基本的程序構(gòu)建模塊;而裝箱類型屬于普通的 Java 類,只不過是對基本類型的一種封裝。由于裝箱類型是對象,因此在內(nèi)存中存在額外開銷。比如,整型在內(nèi)存中占用4 字節(jié),整型對象卻要占用 16 字節(jié)。這一情況在數(shù)組上更加嚴(yán)重,整型數(shù)組中的每個(gè)元素只占用基本類型的內(nèi)存,而整型對象數(shù)組中,每個(gè)元素都是內(nèi)存中的一個(gè)指針,指向 Java堆中的某個(gè)對象。在最壞的情況下,同樣大小的數(shù)組,Integer[] 要比 int[] 多占用 6 倍內(nèi)存。

將基本類型轉(zhuǎn)換為裝箱類型,稱為裝箱,反之則稱為拆箱,兩者都需要額外的計(jì)算開銷。對于需要大量數(shù)值運(yùn)算的算法來說,裝箱和拆箱的計(jì)算開銷,以及裝箱類型占用的額外內(nèi)存,會明顯減緩程序的運(yùn)行速度。

為了減小這些性能開銷,Stream 類的某些方法對基本類型和裝箱類型做了區(qū)分。高階函數(shù) mapToLong 和其他類似函數(shù)即為該方面的一個(gè)嘗試。在 Java 8 中,僅對整型、長整型和雙浮點(diǎn)型做了特殊處理,因?yàn)樗鼈冊跀?shù)值計(jì)算中用得最多,特殊處理后的系統(tǒng)性能提升效果最明顯。

如有可能,應(yīng)盡可能多地使用對基本類型做過特殊處理的方法,進(jìn)而改善性能。這些特殊的 Stream 還提供額外的方法,避免重復(fù)實(shí)現(xiàn)一些通用的方法,讓代碼更能體現(xiàn)出數(shù)值計(jì)算的意圖。

需求:需要計(jì)算出公司部門利潤的平均值,最大值,最小值,以及利潤總和。

LongSummaryStatistics longSummaryStatistics = departmentList
    .stream()
    .mapToLong(Department::getDepartProfit)
    .summaryStatistics();
System.out.println("利潤最大值"+longSummaryStatistics.getMax());
System.out.println("利潤最小值"+longSummaryStatistics.getMin());
System.out.println("利潤平均值"+longSummaryStatistics.getAverage());
System.out.println("利潤總和"+longSummaryStatistics.getSum());

這些統(tǒng)計(jì)值在所有特殊處理的 Stream,如 DoubleStream、LongStream 中都可以得出。如無需全部的統(tǒng)計(jì)值,也可分別調(diào)用 min、max、average 或 sum 方法獲得單個(gè)的統(tǒng)計(jì)值,同樣,三種基本類型對應(yīng)的特殊 Stream 也都包含這些方法。

6. 數(shù)據(jù)并行化

并 行 化 操 作 流 只 需 改 變 一 個(gè) 方 法 調(diào) 用。 如 果 已 經(jīng) 有 一 個(gè) Stream 對 象, 調(diào) 用 它 的parallel 方法就能讓其擁有并行操作的能力。如果想從一個(gè)集合類創(chuàng)建一個(gè)流,調(diào)用parallelStream 就能立即獲得一個(gè)擁有并行能力的流。

需求:并行的統(tǒng)計(jì)公司的所有的人員。

Set<Person> collect = departmentList.stream()
		.parallel()
		.flatMap(e -> e.getPersons().stream()).collect(Collectors.toSet());
Set<Person> collect1 = departmentList.parallelStream()
		.flatMap(e -> e.getPersons().stream()).collect(Collectors.toSet());

在底層,并行流還是沿用了 fork/join 框架。fork 遞歸式地分解問題,然后每段并行執(zhí)行,最終由 join 合并結(jié)果,返回最后的值。文章來源地址http://www.zghlxwxcb.cn/news/detail-607958.html

到了這里,關(guān)于Java8 函數(shù)式編程stream流的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Java8 Stream流的合并

    最近的需求里有這樣一個(gè)場景,要校驗(yàn)一個(gè)集合中每個(gè)對象的多個(gè)Id的有效性。比如一個(gè)Customer對象,有3個(gè)Id: id1 , id2 , id3 ,要把這些Id全部取出來,然后去數(shù)據(jù)庫里查詢它們是否存在。 通常情況下,我們都是從集合中取出對象的某一個(gè)字段,像這樣: 現(xiàn)在要取3個(gè)字段,

    2024年02月02日
    瀏覽(29)
  • Java8中Stream詳細(xì)用法大全

    Java8中Stream詳細(xì)用法大全

    Java 8 是一個(gè)非常成功的版本,這個(gè)版本新增的Stream,配合同版本出現(xiàn)的Lambda ,給我們操作集合(Collection)提供了極大的便利。Stream流是JDK8新增的成員,允許以聲明性方式處理數(shù)據(jù)集合,可以把Stream流看作是遍歷數(shù)據(jù)集合的一個(gè)高級迭代器。Stream 是 Java8 中處理集合的關(guān)鍵抽

    2023年04月08日
    瀏覽(31)
  • Java8的Stream流的學(xué)習(xí)

    Stream可以由數(shù)組或集合創(chuàng)建,對流的操作分為兩種: 中間操作,每次返回一個(gè)新的流,可以有多個(gè)。 終端操作,每個(gè)流只能進(jìn)行一次終端操作,終端操作結(jié)束后流無法再次使用。終端操作會產(chǎn)生一個(gè)新的集合或值。 stream和parallelStream的簡單區(qū)分:?stream是順序流,由主線程按

    2024年02月07日
    瀏覽(26)
  • Java8 Stream 之groupingBy 分組講解

    本文主要講解:Java 8 Stream之Collectors.groupingBy()分組示例 Collectors.groupingBy() 分組之常見用法 功能代碼: /** ?? ? * 使用java8 stream groupingBy操作,按城市分組list ?? ? */ ?? ?public void groupingByCity() { ?? ??? ?MapString, ListEmployee map = employees.stream().collect(Collectors.groupingBy(Employee::getCi

    2024年02月13日
    瀏覽(25)
  • Java8 Stream流處理樹形結(jié)構(gòu)數(shù)據(jù)

    參考資料 Java8新特性-使用Stream流遞歸實(shí)現(xiàn)遍歷樹形結(jié)構(gòu) ID為2,6,11的Menu 是 ID為1的Menu子節(jié)點(diǎn) ID為3,4,5的Menu 是 ID為2的Menu子節(jié)點(diǎn) ?? 注意 是下面這種寫法的一種更簡單的寫法

    2024年02月01日
    瀏覽(21)
  • Java8的stream之groupingBy()分組排序

    Java8的stream之groupingBy()分組排序

    groupingBy()是Stream API中最強(qiáng)大的收集器Collector之一,提供與SQL的GROUP BY子句類似的功能。 需要指定一個(gè)屬性才能使用,通過該屬性執(zhí)行分組。我們通過提供功能接口的實(shí)現(xiàn)來實(shí)現(xiàn)這一點(diǎn) - 通常通過傳遞lambda表達(dá)式。 TreeMap默認(rèn)按照key升序排序,collectPlan.descendingMap()可以進(jìn)行降序排

    2024年02月12日
    瀏覽(24)
  • java8 Stream流常用方法(持續(xù)更新中...)

    java8 Stream流常用方法(持續(xù)更新中...)

    操作對象 模擬數(shù)據(jù) 操作 打印結(jié)果 打印結(jié)果 注意:異常自己捕捉,就比如這里String轉(zhuǎn)Intger就可能出現(xiàn)NumberFormatException異常 打印結(jié)果 打印結(jié)果 斷點(diǎn)查看 打印結(jié)果 斷點(diǎn)查看 持續(xù)更新中…

    2024年04月28日
    瀏覽(28)
  • Java8 Stream流常見操作--持續(xù)更新中

    Java8 Stream流是一種處理數(shù)據(jù)集合的方式,它可以對集合進(jìn)行一系列的操作,包括過濾、映射、排序等,從而實(shí)現(xiàn)對集合中元素的處理和轉(zhuǎn)換。Stream流是一種惰性求值的方式,只有在需要返回結(jié)果時(shí)才會執(zhí)行實(shí)際操作,這種方式可以提高程序的性能。 延遲執(zhí)行:Stream流中的操作

    2024年02月11日
    瀏覽(42)
  • Java8-使用stream.sorted()對List排序

    1.流的定義 Stream 中文稱為 “流”,通過將集合轉(zhuǎn)換為這么一種叫做 “流” 的元素序列,通過聲明性方式,能夠?qū)现械拿總€(gè)元素進(jìn)行一系列并行或串行的操作! 如果流中的元素的類實(shí)現(xiàn)了 Comparable 接口,即有自己的排序規(guī)則,那么可以直接調(diào)用 sorted() 方法對元素進(jìn)行排

    2024年02月16日
    瀏覽(93)
  • JAVA8中l(wèi)ist.stream()的一些簡單使用

    為函數(shù)式編程而生。對stream的任何修改都不會修改背后的數(shù)據(jù)源,比如對stream執(zhí)行過濾操作并不會刪除被過濾的元素,而是會產(chǎn)生一個(gè)不包含被過濾元素的新stream。 stream上的操作并不會立即執(zhí)行,只有等到用戶真正需要結(jié)果的時(shí)候才會執(zhí)行。 stream只能被使用一次,一旦遍歷

    2024年02月03日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包