欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java8新特性 StreamAPI實例詳解

 更新時間:2022年11月02日 11:48:28   作者:我一定有辦法  
這篇文章主要為大家介紹了Java8新特性 StreamAPI實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Stream結(jié)果收集

面試官:說說你常用的StreamAPI。

結(jié)果收集到集合中

    public static void main(String[] args){
        // Stream<String> stream = Stream.of("aa", "bb", "cc");
        List<String> list = Stream.of("aa", "bb", "cc","aa")
                .collect(Collectors.toList());
        System.out.println(list);
        // 收集到 Set集合中
        Set<String> set = Stream.of("aa", "bb", "cc", "aa")
                .collect(Collectors.toSet());
        System.out.println(set);
        // 如果需要獲取的類型為具體的實現(xiàn),比如:ArrayList HashSet
        ArrayList<String> arrayList = Stream.of("aa", "bb", "cc", "aa")
                //.collect(Collectors.toCollection(() -> new ArrayList<>()));
                .collect(Collectors.toCollection(ArrayList::new));
        System.out.println(arrayList);
        HashSet<String> hashSet = Stream.of("aa", "bb", "cc", "aa")
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(hashSet);
    }

輸出:

[aa, bb, cc, aa]
[aa, bb, cc]
[aa, bb, cc, aa]
[aa, bb, cc]

結(jié)果收集到數(shù)組中

Stream中提供了toArray方法來將結(jié)果放到一個數(shù)組中,返回值類型是Object[],如果我們要指定返回的類型,那么可以使用另一個重載的toArray(IntFunction f)方法。

    public static void main(String[] args){
        Object[] objects = Stream.of("aa", "bb", "cc", "aa")
                .toArray(); // 返回的數(shù)組中的元素是 Object類型
        System.out.println(Arrays.toString(objects));
        // 如果我們需要指定返回的數(shù)組中的元素類型
        String[] strings = Stream.of("aa", "bb", "cc", "aa")
                .toArray(String[]::new);
        System.out.println(Arrays.toString(strings));
    }

對流中的數(shù)據(jù)做聚合計算

當(dāng)我們使用Stream流處理數(shù)據(jù)后,可以像數(shù)據(jù)庫的聚合函數(shù)一樣對某個字段進(jìn)行操作,比如獲得最大值,最小值,求和,平均值,統(tǒng)計數(shù)量。

    public static void main(String[] args) {
        // 獲取年齡的最大值
        Optional<Person> maxAge = Stream.of(
                new Person("張三", 18)
                , new Person("李四", 22)
                , new Person("張三", 13)
                , new Person("王五", 15)
                , new Person("張三", 19)
        ).collect(Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge()));
        System.out.println("最大年齡:" + maxAge.get());
        // 獲取年齡的最小值
        Optional<Person> minAge = Stream.of(
                new Person("張三", 18)
                , new Person("李四", 22)
                , new Person("張三", 13)
                , new Person("王五", 15)
                , new Person("張三", 19)
        ).collect(Collectors.minBy((p1, p2) -> p1.getAge() - p2.getAge()));
        System.out.println("最新年齡:" + minAge.get());
        // 求所有人的年齡之和
        Integer sumAge = Stream.of(
                new Person("張三", 18)
                , new Person("李四", 22)
                , new Person("張三", 13)
                , new Person("王五", 15)
                , new Person("張三", 19)
        )
                //.collect(Collectors.summingInt(s -> s.getAge()))
                .collect(Collectors.summingInt(Person::getAge))
                ;
        System.out.println("年齡總和:" + sumAge);
        // 年齡的平均值
        Double avgAge = Stream.of(
                new Person("張三", 18)
                , new Person("李四", 22)
                , new Person("張三", 13)
                , new Person("王五", 15)
                , new Person("張三", 19)
        ).collect(Collectors.averagingInt(Person::getAge));
        System.out.println("年齡的平均值:" + avgAge);
        // 統(tǒng)計數(shù)量
        Long count = Stream.of(
                new Person("張三", 18)
                , new Person("李四", 22)
                , new Person("張三", 13)
                , new Person("王五", 15)
                , new Person("張三", 19)
        ).filter(p->p.getAge() > 18)
                .collect(Collectors.counting());
        System.out.println("滿足條件的記錄數(shù):" + count);
    }

對流中數(shù)據(jù)做分組操作

當(dāng)我們使用Stream流處理數(shù)據(jù)后,可以根據(jù)某個屬性將數(shù)據(jù)分組。

    public static void main(String[] args){
        // 根據(jù)賬號對數(shù)據(jù)進(jìn)行分組
        Map<String, List<Person>> map1 = Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).collect(Collectors.groupingBy(Person::getName));
        map1.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v));
        System.out.println("-----------");
        // 根據(jù)年齡分組 如果大于等于18 成年否則未成年
        Map<String, List<Person>> map2 = Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).collect(Collectors.groupingBy(p -> p.getAge() >= 18 ? "成年" : "未成年"));
        map2.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v));
    }

輸出結(jié)果:

k=李四    v=[Person{name='李四', age=22, height=177}, Person{name='李四', age=15, height=166}]
k=張三    v=[Person{name='張三', age=18, height=175}, Person{name='張三', age=14, height=165}, Person{name='張三', age=19, height=182}]
-----------
k=未成年    v=[Person{name='張三', age=14, height=165}, Person{name='李四', age=15, height=166}]
k=成年    v=[Person{name='張三', age=18, height=175}, Person{name='李四', age=22, height=177}, Person{name='張三', age=19, height=182}]

多級分組: 先根據(jù)name分組然后根據(jù)年齡分組。

    public static void main(String[] args){
        // 先根據(jù)name分組,然后根據(jù)age(成年和未成年)分組
        Map<String,Map<Object,List<Person>>> map =  Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).collect(Collectors.groupingBy(
                Person::getName
                ,Collectors.groupingBy(p->p.getAge()>=18?"成年":"未成年"
                )
        ));
        map.forEach((k,v)->{
            System.out.println(k);
            v.forEach((k1,v1)->{
                System.out.println("\t"+k1 + "=" + v1);
            });
        });
    }

輸出結(jié)果:

李四
    未成年=[Person{name='李四', age=15, height=166}]
    成年=[Person{name='李四', age=22, height=177}]
張三
    未成年=[Person{name='張三', age=14, height=165}]
    成年=[Person{name='張三', age=18, height=175}, Person{name='張三', age=19, height=182}]

對流中的數(shù)據(jù)做分區(qū)操作

Collectors.partitioningBy會根據(jù)值是否為true,把集合中的數(shù)據(jù)分割為兩個列表,一個true列表,一個false列表。

    public static void main(String[] args){
        Map<Boolean, List<Person>> map = Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).collect(Collectors.partitioningBy(p -> p.getAge() > 18));
        map.forEach((k,v)-> System.out.println(k+"\t" + v));
    }

輸出結(jié)果:

false    [Person{name='張三', age=18, height=175}, Person{name='張三', age=14, height=165}, Person{name='李四', age=15, height=166}]
true    [Person{name='李四', age=22, height=177}, Person{name='張三', age=19, height=182}]

對流中的數(shù)據(jù)做拼接

Collectors.joining會根據(jù)指定的連接符,將所有的元素連接成一個字符串。

    public static void main(String[] args){
        String s1 = Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).map(Person::getName)
                .collect(Collectors.joining());
        // 張三李四張三李四張三
        System.out.println(s1);
        String s2 = Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).map(Person::getName)
                .collect(Collectors.joining("_"));
        // 張三_李四_張三_李四_張三
        System.out.println(s2);
        String s3 = Stream.of(
                new Person("張三", 18, 175)
                , new Person("李四", 22, 177)
                , new Person("張三", 14, 165)
                , new Person("李四", 15, 166)
                , new Person("張三", 19, 182)
        ).map(Person::getName)
                .collect(Collectors.joining("_", "###", "$$$"));
        // ###張三_李四_張三_李四_張三$$$
        System.out.println(s3);
    }

并行的Stream流

串行的Stream流

我們前面使用的Stream流都是串行,也就是在一個線程上面執(zhí)行。

并行流

parallelStream其實就是一個并行執(zhí)行的流,它通過默認(rèn)的ForkJoinPool,可以提高多線程任務(wù)的速度。

獲取并行流

我們可以通過兩種方式來獲取并行流。

  • 通過List接口中的parallelStream方法來獲取
  • 通過已有的串行流轉(zhuǎn)換為并行流(parallel)
    public static void main(String[] args){
        List<Integer> list = new ArrayList<>();
        // 通過List 接口 直接獲取并行流
        Stream<Integer> integerStream = list.parallelStream();
        // 將已有的串行流轉(zhuǎn)換為并行流
        Stream<Integer> parallel = Stream.of(1, 2, 3).parallel();
    }

并行流操作

    public static void main(String[] args){
        Stream.of(1,4,2,6,1,5,9)
                .parallel() // 將流轉(zhuǎn)換為并發(fā)流,Stream處理的時候就會通過多線程處理
                .filter(s->{
                    System.out.println(Thread.currentThread() + " s=" +s);
                    return s > 2;
                }).count();
    }

并行流和串行流對比

我們通過for循環(huán),串行Stream流,并行Stream流來對500000000億個數(shù)字求和。來看消耗時間。

public class Test {
    private static long times = 500000000;
    private  long start;
    @Before
    public void befor(){
        start = System.currentTimeMillis();
    }
    @After
    public void end(){
        long end = System.currentTimeMillis();
        System.out.println("消耗時間:" + (end - start));
    }
    /**
     * 普通for循環(huán) 消耗時間:138
     */
    @Test
    public void test01(){
        System.out.println("普通for循環(huán):");
        long res = 0;
        for (int i = 0; i < times; i++) {
            res += i;
        }
    }
    /**
     * 串行流處理
     *   消耗時間:203
     */
    @Test
    public void test02(){
        System.out.println("串行流:serialStream");
        LongStream.rangeClosed(0,times)
                .reduce(0,Long::sum);
    }
    /**
     * 并行流處理 消耗時間:84
     */
    @Test
    public void test03(){
        LongStream.rangeClosed(0,times)
                .parallel()
                .reduce(0,Long::sum);
    }
}

通過案例我們可以看到parallelStream的效率是最高的。

Stream并行處理的過程會分而治之,也就是將一個大的任務(wù)切分成了多個小任務(wù),這表示每個任務(wù)都是一個線程操作。

線程安全問題

在多線程的處理下,肯定會出現(xiàn)數(shù)據(jù)安全問題。如下:

    @Test
    public void test(){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            list.add(i);
        }
        System.out.println(list.size());
        List<Integer> listNew = new ArrayList<>();
        // 使用并行流來向集合中添加數(shù)據(jù)
        list.parallelStream()
                //.forEach(s->listNew.add(s));
                .forEach(listNew::add);
        System.out.println(listNew.size());// 839
    }

針對這個問題,我們的解決方案有哪些呢?

  • 加同步鎖
  • 使用線程安全的容器
  • 通過Stream中的toArray/collect操作

以上就是Java8新特性 StreamAPI實例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java8新特性 StreamAPI的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java并發(fā)控制機制詳解

    Java并發(fā)控制機制詳解

    這篇文章主要為大家詳細(xì)介紹了Java并發(fā)控制機制,什么是Java并發(fā)控制機制,Java并發(fā)控制機制的作用,感興趣的小伙伴們可以參考一下
    2016-08-08
  • springboot中的@value取不到正確的值問題

    springboot中的@value取不到正確的值問題

    這篇文章主要介紹了springboot中的@value取不到正確的值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Spring實戰(zhàn)之緩存使用condition操作示例

    Spring實戰(zhàn)之緩存使用condition操作示例

    這篇文章主要介紹了Spring實戰(zhàn)之緩存使用condition操作,結(jié)合實例形式分析了Spring緩存使用condition具體配置、屬性、領(lǐng)域模型等相關(guān)操作技巧與注意事項,需要的朋友可以參考下
    2020-01-01
  • 基于SpringBoot和Leaflet的行政區(qū)劃地圖掩膜效果實戰(zhàn)教程

    基于SpringBoot和Leaflet的行政區(qū)劃地圖掩膜效果實戰(zhàn)教程

    本文講解的是一種圖層級的掩膜,即使用行政區(qū)劃圖層來進(jìn)行掩膜,使用場景為,用戶只需要在地圖頁面中展示目標(biāo)行政區(qū)劃內(nèi)的影像信息,對于行政邊界外的影像,這篇文章主要介紹了基于SpringBoot和Leaflet的行政區(qū)劃地圖掩膜效果實戰(zhàn),需要的朋友可以參考下
    2024-05-05
  • JAVA內(nèi)存空間相關(guān)知識匯總

    JAVA內(nèi)存空間相關(guān)知識匯總

    這篇文章主要介紹了JAVA內(nèi)存空間相關(guān)知識,文中介紹的非常詳細(xì),代碼幫助大家更好的參考和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • java實現(xiàn)上傳和下載工具類

    java實現(xiàn)上傳和下載工具類

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)上傳和下載工具類,文件上傳到ftp服務(wù)工具類,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java Online Exam在線考試系統(tǒng)的實現(xiàn)

    Java Online Exam在線考試系統(tǒng)的實現(xiàn)

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+springboot+vue+jsp+mysql+maven實現(xiàn)Online Exam在線考試系統(tǒng),大家可以在過程中查缺補漏,提升水平
    2021-11-11
  • Spring?Boot中的max-http-header-size配置方式

    Spring?Boot中的max-http-header-size配置方式

    這篇文章主要介紹了Spring?Boot中的max-http-header-size配置方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Mybatis注解方式完成輸入?yún)?shù)為list的SQL語句拼接方式

    Mybatis注解方式完成輸入?yún)?shù)為list的SQL語句拼接方式

    這篇文章主要介紹了Mybatis注解方式完成輸入?yún)?shù)為list的SQL語句拼接方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 關(guān)于maven:pom文件的使用解析

    關(guān)于maven:pom文件的使用解析

    這篇文章主要介紹了關(guān)于maven:pom文件的使用說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評論