jdk新特性


 

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 注意:源發行版1.8需要目標發行版1.8所以需要到setting中去設置java compiler
 * 1.Lambda表達式取代了匿名類,取消了模板,它將允許我們將行爲傳到函數裏,lambda在java中又叫做匿名函數或則閉包
 * Lambda方法在編譯器內部被翻譯成私有方法,並派發 invokedynamic 字節碼指令來進行調用
 * 2.stream函數式操作流元素集合
 */
public class practicejdk8<T> {
    public static void main(String[] args) {

        /**********************************lambda表達式************************************/

        System.out.println("java泛型" + new practicejdk8<String>().getList());
        /**
         * 1.lamda表達式替換傳統的開啓線程的方式
         */
        //傳統
        new Thread(new Runnable() {
            public void run() {
                System.out.println("傳統的通過runable實現開啓線程的方式");
            }
        }).start();
        //jdk8
        new Thread(() -> System.out.println("jdk8採用的通過runable開啓線程的方式")).start();

        /**
         * 2.lamda表達式進行事件處理,例如swing中的事件監聽代碼
         */
        //傳統
        JButton show = new JButton("showButton");
        show.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("傳統方式完成事件監聽");
            }
        });
        //jdk8
        show.addActionListener((e) -> {
            System.out.println("jdk8採用的方式完成事件監聽");
        });

        /**
         *3.使用lambda表達式對列表進行迭代
         */
        //傳統
        List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        for (Object feature : features) {
            System.out.print("傳統方式遍歷集合:" + feature + "\n");
        }

        //jdk8
        features.forEach(n -> {
            System.out.print("jdk8遍歷集合:" + n + "\n");
        });

        /**
         * 場景4.支持函數式接口Predicate
         */
        List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
        filter(languages, (str) -> str.toString().length() > 4);

        /**
         * 場景5.新的map reduce
         */
        List<Integer> costBeforeTax = Arrays.asList(100, 200, 300, 400, 500);
        //傳統方式
        for (Integer cost : costBeforeTax) {
            double price = cost + 0.12 * cost;
            System.out.println(price);
        }
        //jdk8方式
        System.out.println("======================");
        costBeforeTax.stream().map((cost) -> cost + 0.12 * cost).forEach((cos) -> {
            System.out.println(cos);
        });

        double bill = costBeforeTax.stream().map((cost) -> cost + 0.12 * cost).reduce((sum, cost) -> sum + cost).get();
        System.out.printf("total:" + bill);

        /**
         * 場景6.通過過濾創建一個String列表
         */
        List<String> stringList = Arrays.asList("try", "to", "do", "what you want");
        List<String> filtered = stringList.stream().filter((x) -> x.length() > 2).collect(Collectors.toList());
        System.out.printf("Original List : %s, filtered list : %s %n", stringList, filtered);

        /**
         * 場景7.對列表的每個元素利用函數
         */
        List<String> beautyWords = Arrays.asList("memories", "beautiful", "very", "hurt", "memories", "memories of the past", "but", "can",
                "not", "go", "back");
        String words = beautyWords.stream().map((x) -> x.toUpperCase()).collect(Collectors.joining(" "));
        System.out.println("回憶很美,很傷,回憶只是回不到過去的記憶" + words);

        /**
         * 場景8.利用distinct對集合列表去重,創建一個子列表
         */
        List<String> distinctWords = beautyWords.stream().map((x) -> x.toLowerCase()).distinct().collect(Collectors.toList());
        System.out.println(distinctWords);

        /**
         * 場景9.利用IntSummaryStatistics計算集合中的最大值,最小值,總和以及平均值
         */
        List<Integer> prime = Arrays.asList(1, 3, 5, 7, 9, 11, 13, 17, 19);
        IntSummaryStatistics statistics = prime.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("當前集合中最大值是:" + statistics.getMax() + ",最小值:" + statistics.getMin() + ",總共的數字:" + statistics.getCount() + ",平均數:"
                + statistics.getAverage() + ",總和:" + statistics.getSum());

        /**********************************Stream函數式操作流元素集合************************************/
        List<Integer> nums = Arrays.asList(1, 1, null, 2, 3, 4, null, 5, 6, 7, 8, 9, 10);
        System.out.println("求和:" + nums.stream()
                .filter((x) -> x != null)   //過濾
                .distinct()             //去重
                .mapToInt((num) -> num * 1) //map操作
                .skip(2)                //跳過前二條數據
                .limit(4)               //取前四條數據
                .sum())                 //求和
        ;

        /**********************************方法引用************************************/
        //方法引用使用一對冒號 ::
        person p = new person("zhang", "男");
        person p2 = new person("chao", "男");
        List<person> personList = Arrays.asList(p, p2);
        personList.forEach(person -> System.out.println(person.getName()));
        personList.forEach(person::getName);

        /**********************************接口的默認方法************************************/
        formula f = new formula() {
            @Override
            public double calculate(int a) {
                return a;
            }
        };
        System.out.println(f.sqrt(4));

        /**********************************函數式接口配合lambda表達式使用***********************************
         *每一個lambda表達式都對應一個類型,通常是接口類型,並且方法類型和參數通吃是模板類型
         * 而“函數式接口”是指僅僅只包含一個抽象方法的接口
         * 每一個該類型的lambda表達式都會被匹配到這個抽象方法
         * 因爲 默認方法 不算抽象方法,所以你也可以給你的函數式接口添加默認方法
         */
        Converter<String, Integer> stringIntegerConverter = (from) -> Integer.valueOf(from);
        Integer converted = stringIntegerConverter.convert("123");
        System.out.println(converted);

        /****************************************各種函數式接口總結******************************************/
        //predicate接口
        Predicate<String> predicate = (s) -> s.length() > 0;
        predicate.test("foo");              // true
        predicate.negate().test("foo");     // false

        //function
        Function<String, Integer> toInteger = Integer::valueOf;
        Function<String, String> backToString = toInteger.andThen(String::valueOf);
        backToString.apply("123");

        //supplier接口
        Supplier<person> personSupplier = person::new;
        System.out.println(personSupplier.get().toString());

        //Consumer 接口
        Consumer<person> greeter = (a) -> System.out.println("Hello, " + a.getName());
        greeter.accept(new person("Luke", "男"));

        //Comparator 接口
        Comparator<person> personComparator = (po1, po2) -> po1.getName().compareTo(po2.getName());
        person p1 = new person("a", "女");
        int isP1MoreP2 = personComparator.compare(p1, p2);
        int isP2MoreP1 = personComparator.reversed().compare(p1, p2);
        System.out.println(isP1MoreP2 + "," + isP2MoreP1);

        //Optional 接口
        //此接口不是函數式接口而是一個用來防止空指針異常的輔助類
        Optional<String> optional = Optional.of("ask");
        System.out.println(optional.isPresent());

        //filter接口
//        過濾通過一個predicate接口來過濾並只保留符合條件的元素,該操作屬於中間操作,
//        所以我們可以在過濾後的結果來應用其他Stream操作(比如forEach)。forEach需要
//        一個函數來對過濾後的元素依次執行。forEach是一個最終操作,所以我們不能在forEach之後來執行其他Stream操作。
        languages.stream().map((m)->m.toLowerCase()).filter((s)->s.startsWith("ja")).forEach(System.out::println);

        //sort接口
        //需要注意的是排序只創建了一個排列好的stream,而不會影響原有的數據
        languages.stream().sorted().forEach((x)-> System.out.println(x));
        System.out.println(languages);

        //map映射
        //中間操作map將元素根據指定的Function接口來依次將元素轉成另外的對象
        System.out.println("map映射");
        languages.stream().map(String::toUpperCase).sorted((a,b)->b.compareTo(a)).forEach(System.out::println);

        //match匹配
        boolean anyStartsWithA=languages.stream().anyMatch((s)->s.startsWith("J"));
        System.out.println(anyStartsWithA);
        System.out.println(languages.stream().allMatch((s)->s.length()>5));
        System.out.println(languages.stream().noneMatch((s)->s.equals("Javas")));

        //count 計數
        System.out.println(languages.stream().filter(s->s.length()>4).count());

        //reduce規約
        //這是一個最終操作,允許通過指定的函數來講stream中的多個元素規約爲一個元素,規越後的結果是通過Optional接口表示的
        Optional<String> reduced=languages.stream().reduce((s1,s2)->s1+","+s2);
        reduced.ifPresent(System.out::print);
        System.out.println(languages.stream().reduce((s1,s2)->s1+","+s2).get());

        //並行streams,可以發現parallelStream比stream快了50%多
        //parallelStream 只是做到別浪費cpu,假如本身電腦cpu的負載很大,那還到處用parallel,那並不能起到作用
        //不要在多線程中使用parallelStream,原因同上類似,大家都搶着cpu是沒有提升效果,反而還會加大線程切換開銷
        //會帶來不確定性,請確保每條處理無狀態且沒有關聯
        //考慮nq模型:n可用的數據量,q針對每個數據元素執行的計算量乘積 N*Q 越大,就越有可能獲得並行提速。N x Q > 10000 就會獲得有效提升
        int max = 1000000;
        List<String> values = new ArrayList<>(max);
        for (int i = 0; i < max; i++) {
            UUID uuid = UUID.randomUUID();
            values.add(uuid.toString());
        }

        long t0=System.currentTimeMillis();//串行
        values.stream().sorted().count();
        long t1=System.currentTimeMillis();
        System.out.println("串行排序所花的時間:"+(t1-t0));

        long t2=System.currentTimeMillis();//並行
        values.parallelStream().sorted().count();
        long t3=System.currentTimeMillis();
        System.out.println("串行排序所花的時間:"+(t3-t2));


        //Map,map類型不支持stream
        Map<Integer,String> map=new HashMap<>();
        for(int i=0;i<10;i++){
            map.putIfAbsent(i,"val"+i);//putIfAbsent 不需要我們做額外的存在性檢查
        }
        map.forEach((id,val)-> System.out.println(val));
        map.merge(11,"張超",(value,newValue)->value.concat(newValue)); //map合併,Merge做的事情是如果鍵名不存在則插入,否則則對原鍵對應的值做合併操作並重新插入到map中
        System.out.println(map.get(11));



        /**********************************Annotation 註解************************************/


    }

    public static void filter(List<String> list, Predicate predicate) {
        for (String name : list) {
            if (predicate.test(name)) {
                System.out.println(name + " ");
            }
        }
    }

    /**
     * 集合泛型的示例
     *
     * @return
     */
    public List<T> getList() {
        List<String> list = new CopyOnWriteArrayList<String>();
        list.add("1");
        return (List<T>) list;
    }

    interface formula {
        double calculate(int a);
        default double sqrt(int a) {
            return Math.sqrt(a);
        }
    }

    //函數式接口
    @FunctionalInterface
    interface Converter<F, T> {
        T convert(F from);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章