<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    I want to fly higher
    programming Explorer
    posts - 114,comments - 263,trackbacks - 0
        本篇用代碼示例結合JDk源碼講了Java8引入的工具接口Stream以及新Map接口提供的常用默認方法.
        參考:http://winterbe.com/posts/2014/03/16/java-8-tutorial/

        1.Stream示例

    package com.mavsplus.java8.turtorial.streams;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    import java.util.UUID;

    /**
     * java.util.Stream使用例子
     * 
     * <pre>
     * java.util.Stream表示了某一種元素的序列,在這些元素上可以進行各種操作。Stream操作可以是中間操作,也可以是完結操作。
     * 完結操作會返回一個某種類型的值,而中間操作會返回流對象本身,并且你可以通過多次調用同一個流操作方法來將操作結果串起來。
     * Stream是在一個源的基礎上創建出來的,例如java.util.Collection中的list或者set(map不能作為Stream的源)。
     * Stream操作往往可以通過順序或者并行兩種方式來執行。
     * </pre>
     * 
     * public interface Stream<T> extends BaseStream<T, Stream<T>> {
     * <p>
     * 可以看到Stream是一個接口,其是1.8引入
     * 
     * <p>
     * Java 8中的Collections類的功能已經有所增強,你可以之直接通過調用Collections.stream()或者Collection.
     * parallelStream()方法來創建一個流對象
     * 
     * @author landon
     * @since 1.8.0_25
     
    */
    public class StreamUtilExample {

        private List<String> stringList = new ArrayList<>();

        public StreamUtilExample() {
            init();
        }

        private void init() {
            initStringList();
        }

        /**
         * 初始化字符串列表
         
    */
        private void initStringList() {
            stringList.add("zzz1");
            stringList.add("aaa2");
            stringList.add("bbb2");
            stringList.add("fff1");
            stringList.add("fff2");
            stringList.add("aaa1");
            stringList.add("bbb1");
            stringList.add("zzz2");
        }

        /**
         * Filter接受一個predicate接口類型的變量,并將所有流對象中的元素進行過濾。該操作是一個中間操作,
         * 因此它允許我們在返回結果的基礎上再進行其他的流操作
         * (forEach)。ForEach接受一個function接口類型的變量,用來執行對每一個元素的操作
         * 。ForEach是一個中止操作。它不返回流,所以我們不能再調用其他的流操作
         
    */
        public void useStreamFilter() {
            // stream()方法是Collection接口的一個默認方法
            
    // Stream<T> filter(Predicate<? super T>
            
    // predicate);filter方法參數是一個Predicate函數式接口并繼續返回Stream接口
            
    // void forEach(Consumer<? super T> action);foreach方法參數是一個Consumer函數式接口

            
    // 解釋:從字符串序列中過濾出以字符a開頭的字符串并迭代打印輸出
            stringList.stream().filter((s) -> s.startsWith("a")).forEach(System.out::println);
        }

        /**
         * Sorted是一個中間操作,能夠返回一個排過序的流對象的視圖。流對象中的元素會默認按照自然順序進行排序,
         * 除非你自己指定一個Comparator接口來改變排序規則.
         * 
         * <p>
         * 一定要記住,sorted只是創建一個流對象排序的視圖,而不會改變原來集合中元素的順序。原來string集合中的元素順序是沒有改變的
         
    */
        public void useStreamSort() {
            // Stream<T> sorted();返回Stream接口
            
    // 另外還有一個 Stream<T> sorted(Comparator<? super T>
            
    // comparator);帶Comparator接口的參數
            stringList.stream().sorted().filter((s) -> s.startsWith("a")).forEach(System.out::println);

            // 輸出原始集合元素,sorted只是創建排序視圖,不影響原來集合順序
            stringList.stream().forEach(System.out::println);
        }

        /**
         * map是一個對于流對象的中間操作,通過給定的方法,它能夠把流對象中的每一個元素對應到另外一個對象上。
         * 下面的例子就演示了如何把每個string都轉換成大寫的string.
         * 不但如此,你還可以把每一種對象映射成為其他類型。對于帶泛型結果的流對象,具體的類型還要由傳遞給map的泛型方法來決定。
         
    */
        public void useStreamMap() {
            // <R> Stream<R> map(Function<? super T, ? extends R> mapper);
            
    // map方法參數為Function函數式接口(R_String,T_String).

            
    // 解釋:將集合元素轉為大寫(每個元素映射到大寫)->降序排序->迭代輸出
            
    // 不影響原來集合
            stringList.stream().map(String::toUpperCase).sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);
        }

        /**
         * 匹配操作有多種不同的類型,都是用來判斷某一種規則是否與流對象相互吻合的。所有的匹配操作都是終結操作,只返回一個boolean類型的結果
         
    */
        public void useStreamMatch() {
            // boolean anyMatch(Predicate<? super T> predicate);參數為Predicate函數式接口
            
    // 解釋:集合中是否有任一元素匹配以'a'開頭
            boolean anyStartsWithA = stringList.stream().anyMatch((s) -> s.startsWith("a"));
            System.out.println(anyStartsWithA);

            // boolean allMatch(Predicate<? super T> predicate);
            
    // 解釋:集合中是否所有元素匹配以'a'開頭
            boolean allStartsWithA = stringList.stream().allMatch((s) -> s.startsWith("a"));
            System.out.println(allStartsWithA);

            // boolean noneMatch(Predicate<? super T> predicate);
            
    // 解釋:集合中是否沒有元素匹配以'd'開頭
            boolean nonStartsWithD = stringList.stream().noneMatch((s) -> s.startsWith("d"));
            System.out.println(nonStartsWithD);
        }

        /**
         * Count是一個終結操作,它的作用是返回一個數值,用來標識當前流對象中包含的元素數量
         
    */
        public void useStreamCount() {
            // long count();
            
    // 解釋:返回集合中以'a'開頭元素的數目
            long startsWithACount = stringList.stream().filter((s) -> s.startsWith("a")).count();
            System.out.println(startsWithACount);

            System.out.println(stringList.stream().count());
        }

        /**
         * 該操作是一個終結操作,它能夠通過某一個方法,對元素進行削減操作。該操作的結果會放在一個Optional變量里返回。
         
    */
        public void useStreamReduce() {
            // Optional<T> reduce(BinaryOperator<T> accumulator);
            
    // @FunctionalInterface public interface BinaryOperator<T> extends
            
    // BiFunction<T,T,T> {

            
    // @FunctionalInterface public interface BiFunction<T, U, R> { R apply(T
            
    // t, U u);
            Optional<String> reduced = stringList.stream().sorted().reduce((s1, s2) -> s1 + "#" + s2);

            // 解釋:集合元素排序后->reduce(削減 )->將元素以#連接->生成Optional對象(其get方法返回#拼接后的值)
            reduced.ifPresent(System.out::println);
            System.out.println(reduced.get());
        }

        /**
         * 使用并行流
         * <p>
         * 流操作可以是順序的,也可以是并行的。順序操作通過單線程執行,而并行操作則通過多線程執行. 可使用并行流進行操作來提高運行效率
         
    */
        public void useParallelStreams() {
            // 初始化一個字符串集合
            int max = 1000000;
            List<String> values = new ArrayList<>();

            for (int i = 0; i < max; i++) {
                UUID uuid = UUID.randomUUID();
                values.add(uuid.toString());
            }

            // 使用順序流排序

            long sequenceT0 = System.nanoTime();
            values.stream().sorted();
            long sequenceT1 = System.nanoTime();

            // 輸出:sequential sort took: 51921 ms.
            System.out.format("sequential sort took: %d ms.", sequenceT1 - sequenceT0).println();

            // 使用并行流排序
            long parallelT0 = System.nanoTime();
            // default Stream<E> parallelStream() {
            
    // parallelStream為Collection接口的一個默認方法
            values.parallelStream().sorted();
            long parallelT1 = System.nanoTime();

            // 輸出:parallel sort took: 21432 ms.
            System.out.format("parallel sort took: %d ms.", parallelT1 - parallelT0).println();

            // 從輸出可以看出:并行排序快了一倍多
        }

        public static void main(String[] args) {
            StreamUtilExample example = new StreamUtilExample();

            example.useStreamFilter();
            example.useStreamMap();
            example.useStreamMatch();
            example.useStreamCount();
            example.useStreamReduce();
            example.useParallelStreams();
        }
    }


        2.Map接口中新的默認方法示例

    package com.mavsplus.java8.turtorial.streams;

    import java.util.HashMap;
    import java.util.Map;

    /**
     * map是不支持流操作的。而更新后的map現在則支持多種實用的新方法,來完成常規的任務
     * 
     * @author landon
     * @since 1.8.0_25
     
    */
    public class MapUtilExample {

        private Map<Integer, String> map = new HashMap<>();

        public MapUtilExample() {
            initPut();
        }

        /**
         * 使用更新后的map進行putIfAbsent
         
    */
        private void initPut() {
            // putIfAbsent為Map接口中新增的一個默認方法
            /**
             * <code>
                      default V putIfAbsent(K key, V value) {
                        V v = get(key);
                        if (v == null) {
                            v = put(key, value);
                        }

                        return v;
                      }
                      </code>
             
    */
            // 如果map中有對應K映射的V且不為null則直接返回;否則執行put
            for (int i = 0; i < 10; i++) {
                map.putIfAbsent(i, "value" + i);
            }

            // 放入了一個null元素
            map.putIfAbsent(10null);
            // 替換null
            map.putIfAbsent(10"value10");
            // 因為K-10有映射且不為null則忽略V-value11
            map.putIfAbsent(10"value11");
        }

        /**
         * 使用更新后的map進行for-each
         
    */
        public void forEach() {
            // default void forEach(BiConsumer<? super K, ? super V> action)
            
    // Map接口中新增的默認方法

            
    // @FunctionalInterface public interface BiConsumer<T, U> {void accept(T
            
    // t, U u);
            map.forEach((id, val) -> System.out.println(val));
        }

        /**
         * 使用更新后的map進行compute——->重映射
         
    */
        public void compute() {
            // default V computeIfPresent(K key,BiFunction<? super K, ? super V, ?
            
    // extends V> remappingFunction)

            
    // Map接口中新增的默認方法

            
    // @FunctionalInterface public interface BiFunction<T, U, R> {R apply(T
            
    // t, U u);
            
    // --> V apply(K k,V v)

            
    // ifPresent會判斷key對應的v是否是null,不會null才會compute->否則直接返回null

            
    // 解釋:將K-3映射的value->compute->"value3" + 3 = value33
            map.computeIfPresent(3, (key, val) -> val + key);
            System.out.println(map.get(3));

            // 解釋:這里將K-3映射的value進行重映射->null
            
    // 該方法源碼實現會判斷如果newValue為null則會執行remove(key)方法,將移除key
            map.computeIfPresent(9, (key, val) -> null);
            // 從上面的解釋中得到,輸出為false,因為已經被移除了
            System.out.println(map.containsKey(9));

            // default V computeIfAbsent(K key,Function<? super K, ? extends V>
            
    // mappingFunction)
            
    // 解釋:代碼實現上看,如果K-15映射的值為null,即不存在或者為null,則執行映射->所以本例來看(沒有15的key),該方法相當于插入一個新值
            map.computeIfAbsent(15, (key) -> "val" + key);
            System.out.println(map.containsKey(15));

            // 因為K-4映射的值存在,所以直接返回,即不會重映射,所以輸出依然會是value4
            map.computeIfAbsent(4, key -> "bam");
            System.out.println(map.get(4));
        }

        /**
         * 使用更新后的map進行remove
         
    */
        public void remove() {
            // default boolean remove(Object key, Object value) {
            
    // Map接口中新增的默認方法

            
    // 其源碼實現是
            
    // 1.當前key對應的值和傳入的參數不一致時則直接返回,移除失敗(用的是Objects.equals方法)
            
    // 2.當前key對應的值為null且!containsKey(key),移除失敗(即當前map中根本不存在這個key_【因為有一種情況是有這個key但是key映射的值為null】)
            
    // ->否則執行移除

            /**
             * <code>
             *  default boolean remove(Object key, Object value) {
                    Object curValue = get(key);
                    if (!Objects.equals(curValue, value) ||
                        (curValue == null && !containsKey(key))) {
                        return false;
                    }
                    remove(key);
                    return true;
                }
             * </code>
             
    */
            map.remove(3"value4");
            System.out.println(map.get(3));

            // key和v匹配時則移除成功
            map.remove(3"value33");
            System.out.println(map.get(3));
        }

        /**
         * getOrDefault是一個有用的方法
         
    */
        public void getOrDefault() {
            // default V getOrDefault(Object key, V defaultValue) {
            
    // Map接口中新增的默認方法

            /**
             * <code>
             * default V getOrDefault(Object key, V defaultValue) {
                V v;
                return (((v = get(key)) != null) || containsKey(key))
                    ? v
                    : defaultValue;
                }
             * </code>
             
    */

            // 源碼實現:
            
    // 1.如果對應的key有value且不為null,則直接返回value;如果為null且包含該key,則返回null(總之即必須要有該key)
            
    // 2.如果沒有該key,則用默認值
            String retV = map.getOrDefault("20""not found");
            System.out.println(retV);

            // 加入一個null
            map.putIfAbsent(30null);
            // 輸出null
            System.out.println(map.get(30));
            // 輸出null
            System.out.println(map.getOrDefault(30"value30"));
        }

        /**
         * 合并
         
    */
        public void merge() {
            // default V merge(K key, V value,BiFunction<? super V, ? super V, ?
            
    // extends V> remappingFunction)

            
    // @FunctionalInterface public interface BiFunction<T, U, R> { R apply(T
            
    // t, U u);

            
    // merge為Map接口新增的默認方法

            /**
             * <code>
             default V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
                    Objects.requireNonNull(remappingFunction);
                    Objects.requireNonNull(value);
                    V oldValue = get(key);
                    V newValue = (oldValue == null) ? value :
                               remappingFunction.apply(oldValue, value);
                    if(newValue == null) {
                        remove(key);
                    } else {
                        put(key, newValue);
                    }
                return newValue;
             }
             * </code>
             
    */

            // 其源碼實現:
            
    // 1.分別檢查參數remappingFunction和value是否為null(調用Objects.requireNonNull).->為null則拋出空指針
            
    // 2.判斷oldValue是否為null,如果為null則將傳入的newValue賦值;如果oldValue不為null則執行merge函數
            
    // --->apply(oldValue, value)
            
    // 3.判斷newValue->如果為null則執行移除;否則執行插入

            
    // k-9的值在執行compute方法的時候已經被移除了->所以oldValue為null->所以newValue為傳入的參數value9->執行插入
            
    // 所以這里輸出為value9
            String newValue1 = map.merge(9"value9", (value, newValue) -> value.concat(newValue));
            System.out.println(newValue1);
            System.out.println(map.get(9));

            // k-9的值現在已經為value9了,所以執行merge函數->"value9".concat("concat")->newValue為"value9concat"
            
    // 執行插入,所以這里輸出為value9concat
            String newValue2 = map.merge(9"concat", (value, newValue) -> value.concat(newValue));
            System.out.println(newValue2);
            System.out.println(map.get(9));

            // k-8值存在為value8->執行merge函數->直接返回"NewMerge8"->newValue為"NewMerge8"
            
    // 執行put->所以這里輸出"NewMerge8"
            map.merge(8"merge", (value, newValue) -> "NewMerge8");
            System.out.println(map.get(8));
        }

        public static void main(String[] args) {
            MapUtilExample example = new MapUtilExample();

            example.forEach();
            example.compute();
            example.remove();
            example.getOrDefault();
            example.merge();
        }
    }


    posted on 2014-11-18 20:31 landon 閱讀(24530) 評論(1)  編輯  收藏 所屬分類: Program

    FeedBack:
    # re: Java8之Stream/Map[未登錄]
    2016-01-19 02:13 | jay
    總結的很詳細!  回復  更多評論
      
    主站蜘蛛池模板: 在线人成精品免费视频| 立即播放免费毛片一级| 亚洲福利在线观看| 国产∨亚洲V天堂无码久久久| mm1313亚洲精品国产| 国产一区二区免费在线| 在线免费观看韩国a视频| 热99re久久精品精品免费| 青青青青青青久久久免费观看| 女人18毛片水真多免费播放| 大学生美女毛片免费视频| 免费黄色小视频网站| 国产一级高清免费观看| 免费播放春色aⅴ视频| 亚洲精品国产精品乱码不卞| 亚洲国产a级视频| 国产亚洲欧洲Aⅴ综合一区| 亚洲人成人网站色www| 亚洲AV无码专区国产乱码电影| 亚洲av日韩av高潮潮喷无码| 亚洲综合在线视频| 久久亚洲精品专区蓝色区| 亚洲最大天堂无码精品区| 亚洲aⅴ天堂av天堂无码麻豆| 全部在线播放免费毛片| 三年片免费观看大全国语| 一级毛片免费视频| 一个人免费观看www视频在线| 四虎影视大全免费入口| 亚洲国模精品一区| 亚洲成a人片在线观看日本| 亚洲电影在线播放| 亚洲成aⅴ人片久青草影院按摩| 免费的黄色网页在线免费观看| 两性色午夜视频免费播放| 最近2019年免费中文字幕高清| 成年美女黄网站色大免费视频| 亚洲AV无码一区二区三区国产| 久久精品国产精品亚洲精品 | 18禁黄网站禁片免费观看不卡 | 国产美女视频免费观看的网站 |