1. 程式人生 > >第5篇 stream ---數值流

第5篇 stream ---數值流

**
 * Java 8引入了三個原始型別特化流介面來解決這個問題:IntStream、DoubleStream和
 * LongStream,分別將流中的元素特化為int、long和double,從而避免了暗含的裝箱成本。每
 * 個介面都帶來了進行常用數值歸約的新方法,比如對數值流求和的sum,找到最大元素的max。
 * 此外還有在必要時再把它們轉換回物件流的方法。要記住的是,這些特化的原因並不在於流的復
 * 雜性,而是裝箱造成的複雜性——即類似int和Integer之間的效率差異
 */
public class PrimitiveTypeDemo {
    public static void main(String[] args) {
        List<Dish> menues = Arrays.asList(new Dish("rice", true, 10000, Dish.Type.FISH), new Dish("meat", false, 20000, Dish.Type.FISH), new Dish("dog", true, 30000, Dish.Type.FISH));
        test01(menues);
    }

    /**
     * 1. 對映到數值流:
     * 將流轉換為特化版本的常用方法是mapToInt、mapToDouble和mapToLong。這些方法和前
     * 面說的map方法的工作方式一樣,只是它們返回的是一個特化流,而不是Stream<T>。例如,你
     * 可以像下面這樣用mapToInt對menu中的卡路里求和:
     * 這裡,mapToInt會從每道菜中提取熱量(用一個Integer表示),並返回一個IntStream
     * (而不是一個Stream<Integer>)。然後你就可以呼叫IntStream介面中定義的sum方法,對卡
     * 路里求和了!請注意,如果流是空的,sum預設返回0。IntStream還支援其他的方便方法,如
     * max、min、average等。
     */
    public static void test01(List<Dish> menues) {
        int sum = menues.stream().mapToInt(Dish::getCalories).sum();
        System.out.println(sum);
    }

    /**
     *  轉換回物件流:
     *  同樣,一旦有了數值流,你可能會想把它轉換回非特化流。例如,IntStream上的操作只能
     * 產生原始整數: IntStream 的 map 操作接受的 Lambda 必須接受 int 並返回 int (一個
     * IntUnaryOperator)。但是你可能想要生成另一類值,比如Dish。為此,你需要訪問Stream
     * 介面中定義的那些更廣義的操作。要把原始流轉換成一般流(每個int都會裝箱成一個
     * Integer),可以使用boxed方法,如下所示:
     * @param menues
     */

    public static void test02(List<Dish> menues) {
        IntStream intStream = menues.stream().mapToInt(Dish::getCalories);
        Stream<Integer> boxed = intStream.boxed();

    }

    /**
     * 預設值OptionalInt:
     * 求和的那個例子很容易,因為它有一個預設值:0。但是,如果你要計算IntStream中的最
     * 大元素,就得換個法子了,因為0是錯誤的結果。如何區分沒有元素的流和最大值真的是0的流呢?
     * 前面我們介紹了Optional類,這是一個可以表示值存在或不存在的容器。Optional可以用
     * Integer、String等參考型別來引數化。對於三種原始流特化,也分別有一個Optional原始類
     * 型特化版本:OptionalInt、OptionalDouble和OptionalLong;
     * 例如,要找到IntStream中的最大元素,可以呼叫max方法,它會返回一個OptionalInt:
     * @param menues
     */
    public static void test03(List<Dish> menues) {
        OptionalInt max = menues.stream().mapToInt(Dish::getCalories).max();
        if(max.isPresent()){
            System.out.println("有最大值"+max.getAsInt());
        }else{
            int defaultValue = max.orElse(1);
            System.out.println("沒有最大值,採用預設的最大值"+defaultValue);
        }
    }

}