91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

如何使用java8新特性Stream

發布時間:2021-10-13 11:11:16 來源:億速云 閱讀:149 作者:iii 欄目:編程語言

這篇文章主要介紹“如何使用java8新特性Stream”,在日常操作中,相信很多人在如何使用java8新特性Stream問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何使用java8新特性Stream”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

首先先定義一個菜品類:

  • Dish

public class Dish {
    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;
    
    public boolean isVegetarian() {
        return vegetarian;
    }
    
    //省略set,get,toString方法}

然后創建一個靜態方法,并且設置成類的成員變量,以供測試。

public static List<Dish> getDishes() {
    return Arrays.asList(
        new Dish("pork", false, 800, Dish.Type.MEAT),
        new Dish("beef", false, 700, Dish.Type.MEAT),
        new Dish("chicken", false, 400, Dish.Type.MEAT),
        new Dish("french fries", true, 530, Dish.Type.OTHER),
        new Dish("rice", true, 350, Dish.Type.OTHER),
        new Dish("pizza", true, 550, Dish.Type.OTHER),
        new Dish("prawns", false, 300, Dish.Type.FISH),
        new Dish("salmon", false, 450, Dish.Type.FISH)
    );
}

XNBqZ

好了,現在有個需求,找出菜品中所有小于400卡路里的食物,并且按照卡路里的大小進行排序。

java8之前,甚至有些人在java8之后,都會想著借助一個中間變量保符合要求的菜品,然后排序。

public static List<String> beforeJava8() {
    List<Dish> lowCaloricDishes = new ArrayList<>();
    for (Dish dish : dishes) {
        if (dish.getCalories() < 400) {
            lowCaloricDishes.add(dish);
        }
    }

    lowCaloricDishes.sort(Comparator.comparingInt(Dish::getCalories));//    lowCaloricDishes.sort((d1, d2) -> Integer.compare(d1.getCalories(), d2.getCalories()));    List<String> res = new ArrayList<>();

    for (Dish dish : lowCaloricDishes) {
        res.add(dish.getName());
    }
    return res;
}

由于前一篇文章講過了方法引用,所以這里就直接用,不過下面一行也有普通的Lambda表達式的書寫。

上述寫法有什么問題嗎,可以發現lowCaloricDishes 只使用了一次,真就一個臨時變量。那能不能跳過創建變量的過程,你直接把數據給我,我經過過濾排序后得到想要的呢,就和流水線一樣。

public static List<String> afterJava8() {
    return dishes.stream()
        .filter(dish -> dish.getCalories() < 400)
        .sorted(Comparator.comparing(Dish::getCalories))
        .map(Dish::getName)
        .collect(Collectors.toList());
}
流的定義

從支持數據處理操作的源生成的元素序列

流和集合有點類似,集合是數據結構,主要的目的是存儲和訪問元素,而流的主要目的是為了對元素進行一系列的操作。

通俗入門地來講,集合就相當于你一部電影下載,流就相當于在線觀看。其實只需要把流想成高級的集合即可。流有兩個重要的特點:

  • 流水線: 很多流本身會返回一個流,這樣多個流就能鏈接起來和流水線一般。

  • 內部迭代: 內部迭代也就是把迭代封裝起來,如collect(Collectors.toList) ,與之相對應的外部迭代則是for-each

值得注意的是,和迭代器類似,流只能遍歷一次 ,遍歷完就可以說這個流消費掉了。

流的構建

流的構建

流常用的構建方式有4種,其實要么是借助Stream 類的靜態方法,要么是借助別人的類的靜態方法。

  • 由值創建流

  • 由數組創建流

  • 由文件生成流

  • 由函數生成流

public static void buildStream() throws IOException {
    Stream<String> byValue = Stream.of("java8", "c++", "go");

    Stream<Object> empty = Stream.empty();

    int[] nums = {1, 2, 3, 4, 5};
    IntStream byInts = Arrays.stream(nums);

    Stream<String> byFiles = Files.lines(Paths.get(""));

    Stream<Integer> byFunction1 = Stream.iterate(0, n -> n * 2);
    Stream<Double> byFunction2 = Stream.generate(Math::random);

    Stream<String> java = Stream.of("java");
}
流的操作

可以連接起來的流操作稱為中間操作,關閉流的操作稱為終端操作

通俗地講,返回結果是流的操作稱為中間操作,放回的不是流的操作稱為終端操作。

如何使用java8新特性Stream

image-20210414155605342

通過查找java8接口可以得知到哪些接口是中間操作,哪些接口時終端操作。由于那些接口描述得太過官方,估計我貼了也沒啥人會仔細看,所以想看的直接去官方查閱即可。

流的使用

就按照官網上的java API順序來講述,小插一句,之前我一直沒有學流是主要是因為感覺接口會很多,怎么可能記得了這么多,其實這幾天看才發現真的很少,基本上不用記。

img

img

首先構建好一個數字列表:

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

中間操作

中間操作有去重、過濾、截斷、查看、跳過、排序 ,這些相信大家都能夠明白是什么意思。

public static void midOperation() {
    numbers.stream()
        .distinct()
        .forEach(System.out::println);

    List<Integer> filter = numbers.stream()
        .filter(n -> n % 2 == 0)
        .collect(Collectors.toList());

    numbers.stream()
        .limit(3)
        .forEach(System.out::println);

    numbers.stream()
        .peek(integer -> System.out.println("consume operation:" + integer))
        .forEach(System.out::println);

    List<Integer> skip = numbers.stream()
        .skip(2)
        .collect(Collectors.toList());

    numbers.stream()
        .sorted()
        .forEach(System.out::println);
}
中間操作之映射(map)

需要單獨拎出來說的是映射(map)扁平化映射(flatMap) ,注意,這里的map并不是hashmap的那個map,而是說把什么映射或者說轉化成了什么。

public static void midOperation() {
 List<String> map = numbers.stream()
                .map(Object::toString)   //這里就是把int映射成了string                .collect(Collectors.toList());
}

而對于扁平化映射,現在又有一個需求,現在有個單詞列表如{"hello", "world"},返回里面各不相同的字符,也就是要求返回List<String>

這還不簡單,把單詞映射成一個個字母,再去重就好了。

public static void flatMapDemoNoral() {
    List<String> words = Arrays.asList("hello", "world");
    List<String[]> normal = words.stream()
        .map(str -> str.split(""))
        .distinct()
        .collect(Collectors.toList());
}

如何使用java8新特性Stream

img

雖然確實也能達到效果,但是注意映射所用的函數是split() ,返回的是String[] ,因此整個返回的是List<String[]>

那我映射完后再把每個String[] 數組映射成流

public static void flatMapDemoMap() {
    List<String> words = Arrays.asList("hello", "world");
    List<Stream<String>> usingMap = words.stream()
                .map(str -> str.split(""))
                .map(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
}

雖然摘掉了數組的帽子,但是返回的卻是List<Stream<String>>

flatMap 正是為了解決這種情況的

public static void flatMapDemoFlatMap() {
    List<String> words = Arrays.asList("hello", "world");
    List<String> usingFlatMap = words.stream()
                .map(str -> str.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
}

可以簡單的理解,map是把每個元素映射成了獨立的流,而扁平化map是把元素保存了下來,最后映射成了一個流

查找與匹配

終端操作除了上述寫例子的時候常用的collect()forEach() 還有查找和規約兩種大的方向。

因為沒啥好說的,直接上代碼就完了:

public static void endOperationFindAndMatch() {
    if (dishes.stream().noneMatch(Dish::isVegetarian)) {
        System.out.println("所有的菜品都是非素食");
    }
    if (dishes.stream().allMatch(Dish::isVegetarian)) {
        System.out.println("所有的菜品都是素食");
    }
    if (dishes.stream().anyMatch(Dish::isVegetarian)) {
        System.out.println("菜品中至少有一道菜是素食");
    }

    Optional<Dish> any = dishes.stream()
        .filter(meal -> meal.getCalories() <= 1000)
        .findAny();
    Optional<Dish> first = dishes.stream()
        .filter(meal -> meal.getCalories() <= 1000)
        .findFirst();
}
歸約(計算)

對流的規約操作的話,一般有普通操作也就是能直接調用接口的,還有一種就是借助reduce()

對于普通操作來說,像求和,最大值,最小值這些都是有接口對應的。

public static void endOperationCalculate() {
    long count = dishes.stream()
        .filter(meal -> meal.getCalories() <= 1000)
        .count();
    Optional<Dish> max = dishes.stream()
        .max(Comparator.comparingInt(Dish::getCalories));
    Optional<Dish> min = dishes.stream()
        .min(Comparator.comparing(Dish::getName));

}

但是如果說要求對元素求和,就要使用reduce()

image-20210417114209123

image-20210417114209123

一般使用的是可以接受2個參數,一個是初始值,一個是BinaryOprator<T> 來將兩個元素結合起來產生的新值。

public static void reduceDemo() {
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 5, 5, 5, 6, 7);
    Integer sum = numbers.stream().reduce(0, Integer::sum);
    
    //所有元素相乘也是比較簡單    Integer multi = numbers.stream().reduce(0, (a, b) -> a * b);
    
    //還有求最大值    Optional<Integer> max = numbers.stream().reduce(Integer::max);
}

Optional類

上面一直出現有返回值是Optional<T> ,它是一個容器類代表一個值存在或者不存在,比如一開始的findAny() ,可能找不到符合條件的菜品。Java8引入的目的主要是/為了不要返回容易出現問題的null了。

就說幾個比較常用的api就好了至于其它的可以上網看下官方API,今天說的API已經夠多了

  • isPresent() 將在Optional 包含值的時候返回true,否則返回false

  • ifPresent(Consumer<T> block) 存在值的時候會執行給定的代碼塊

  • get() 存在值就返回值,否則拋出NoSuchElement異常

  • orElse() 存在值就返回,否則就返回一個默認值

public static void optionalDemo() {
    //ifPresent    dishes.stream()
        .filter(Dish::isVegetarian)
        .findAny()
        .ifPresent(dish -> System.out.println(dish.getName()));

    //isPresent    boolean isLowCalories= dishes.stream()
        .filter(dish -> dish.getCalories() <= 1000)
        .findAny()
        .isPresent();
 
    //get    Optional<Dish> optional = dishes.stream()
        .filter(Dish::isVegetarian)
        .findAny();
    if (optional.isPresent()) {
        Dish dish = optional.get();
    }

    //orElse    Dish dishNormal = dishes.stream()
        .filter(Dish::isVegetarian)
        .findAny()
        .orElse(new Dish("java", false, 10000, Dish.Type.OTHER));
}

到此,關于“如何使用java8新特性Stream”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

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

AI

泽州县| 霸州市| 内江市| 富源县| 贵港市| 安岳县| 望江县| 石景山区| 思南县| 凯里市| 吴江市| 营山县| 西乌珠穆沁旗| 客服| 正宁县| 漳平市| 夏津县| 宝鸡市| 文山县| 隆化县| 屯留县| 丰原市| 海原县| 黑水县| 新化县| 宜春市| 松原市| 柏乡县| 思南县| 沂源县| 环江| 新乡县| 北宁市| 嘉峪关市| 淅川县| 肃北| 富裕县| 景泰县| 永昌县| 扶余县| 廉江市|