JDK8 Stream 從入門到裝逼(三)

lambdas中,能夠看到lambda表達式讓代碼更加簡潔、乾淨、容易理解,並容許不須要建立一個類就能夠達到目的。lambdas很好的幫助開發人員更好的表達片斷代碼的意思,Stream對於集合提供一個抽象計算和Fluent接口更能讓程序猿變得爽歪歪。java

###1. 構建stream 初始化stream的幾個方法編程

//1. Stream generate 生成無限個無序的stream
    Stream<String> stream = Stream.generate(() -> UUID.randomUUID().toString());
// 2. of 構造stream
    Stream<Integer> integerStream = Stream.of(1, 2, 4, 6, 3, 9, 7); 	      
//3.集合構造出stream
	Stream<List<Integer>> inputStream = Stream.of(
		    Arrays.asList(1),
		    Arrays.asList(2, 3),
		    Arrays.asList(4, 5, 6)
	);

###2. 能夠怎樣用streamapi

/**
 * jdk8 stream 用法
 * Created by kaishui on 2016/9/3.
 */
public class JDK_07StreamTest {
    static class User {
        private String name;
        private String password;

        public User(String name, String password) {
            this.name = name;
            this.password = password;
        }

        //省略getter and setter
    }


    public static void main(String[] args) {
        List<User> userList = new ArrayList<User>();
        userList.add(new User("name1", "passowrd1"));
        userList.add(new User("name4321", "passowrd4"));
        userList.add(new User("name321", "passowrd3"));
        userList.add(new User("kaishui", "kaishuiPassword"));
        userList.add(new User("name21", "passowrd2"));

        //1. 在jdk7以前的代碼中,也許咱們常常會這樣寫
        List<User> otherUsers = new ArrayList<>();
        for (User u : userList) {
            //獲取含有 "name"的User
            if (null != u.getName() && u.getName().indexOf("name") >= 0) {
                otherUsers.add(u);
            }
        }
        //按照名字長度排序
        Collections.sort(otherUsers, new Comparator<User>() {
            @Override
            public int compare(User u1, User u2) {
                return u1.getName().length() - u2.getName().length();
            }
        });
        //打印
        for (User u : otherUsers) {
            System.out.println(u.getName());
        }
        System.out.println("-------我是一條分割線1---------");
        System.out.println("-------jdk8 示例---------");
        // 2. jdk8 使用stream操做集合
        List<String> nameList = userList.stream()
                .filter(u -> null != u.getName() && u.getName().indexOf("name") >= 0)	//過濾結果
                .sorted((u1, u2) -> u1.getName().length() - u2.getName().length())		//排序
                .map(u -> u.getName())													//提取
                .collect(Collectors.toList());											//把上述步驟後的結果轉換成list
        //打印
        nameList.forEach(System.out::println);
    }
}

執行結果:app

name1
name21
name321
name4321
-------我是一條分割線1---------
-------jdk8---------
name1
name21
name321
name4321

上面的例子,大概瞭解stream的用法,下面分點介紹一下: JDK8 collection中已經實現了一個default的stream方法dom

1. stream() 在集合collection中新建一個stream的管道,有點相似Linux命令中 grep or awk的用法。
2. filter(Predicate) 過濾條件, 看到Predicate應該能夠想到就是過濾數據。
3. sorted(Comparator) 根據Comparator排序,英語國家的就是爽,寫接口均可以省註釋了.
4. map(Function) 提取計算,根據Funtion的做用,咱們也知道,<T,R>輸入一個T,返回一個R。
5. collect(Collectors.toList()) 把上述操做stream的結果轉爲另一個集合。

若是不瞭解predicate、function的用法,能夠系列篇之函數式接口編程ide

###3. stream 懶加載函數

// 1. of 構造 Stream<Integer>
Stream<Integer> integerStream = Stream.of(1, 2, 4, 6, 3, 9, 7).map(x -> x / 0);
System.out.println("-------我是一條分割線--------");

執行結果:ui

-------我是一條分割線--------

上述看到,map(x -> x/0)並無執行,若是換成下面代碼:this

// 1. of 構造 Stream<Integer>
Stream<Integer> integerStream = Stream.of(1, 2, 4, 6, 3, 9, 7).map(x -> x / 0);
List<Integer> list = integerStream.collect(Collectors.toList());
System.out.println("-------我是一條分割線--------");

執行結果:lua

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.iu.jdk8.JDK_09StreamLazyLoadTest.lambda$main$0(JDK_09StreamLazyLoadTest.java:19)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at com.iu.jdk8.JDK_09StreamLazyLoadTest.main(JDK_09StreamLazyLoadTest.java:20)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

stream只有真正使用到的時候纔去真正的執行。

###4. stream 鏈式編程何時纔是結束

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

當steam趕上這些方法纔算是結束,其餘的方法,例如:

map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

仍是能夠在上一個操做結果上繼續操做,例如:根據條件filter -> sort -> map

List<User> userList = new ArrayList<User>();
        for (int i = 0; i < 10; i++) {
            userList.add(new User("name" + i, "passowrd" + i, i));
        }
 List<String> nameList = userList.stream()
                .filter(u -> null != u.getName() && u.getName().indexOf("name") >= 0)	//過濾結果
                .sorted((u1, u2) -> u1.getName().length() - u2.getName().length())		//排序
                .map(u -> u.getName())													//提取
                .collect(Collectors.toList());											//把上述步驟後的結果轉換成list

###5. stream api 例子

####5.1 distinct 去重

Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).distinct().sorted().forEach(System.out::print);

//執行結果: 1234679

####5.2 skip 跳過條數 limit 限定結果返回幾條

Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).skip(2).limit(3).forEach(System.out::print);
 //執行結果:463

####5.3 fitler 參數爲:Predicate 過濾知足條件的結果, Count 統計條數

//獲取集合中7的個數
long sum = Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).filter(x -> x == 7).count();
System.out.println("sum = " + sum);

 //執行結果: sum = 2

####5.4 flatMap 使數據扁平化處理 不少情景,咱們都會用到一個類中有List<Object>屬性,怎樣轉化成Strean<Object>呢,這是flatMap就該出手了

public class JDK_08StreamFlatMapTest {
    static class User {
        private String name;
        private String password;
        private int no;

        public User(String name, String password, int no) {
            this.name = name;
            this.password = password;
            this.no = no;
        }

        //省略getter and setter
        
    }

    //班級
    static class Clazz{
        List<User> users;
        //省略getter and setter
    }


    public static void main(String[] args) {
        List<User> girlList = new ArrayList<User>();
        List<User> boyList = new ArrayList<User>();
        for (int i = 0; i < 10; i++) {
            girlList.add(new User("girl" + i, "passowrd" + i, i));
            boyList.add(new User("boy" + i, "passowrd" + i, i));
        }

        //班級1
        Clazz clazz = new Clazz();
        //班級2
        Clazz clazz2 = new Clazz();
        girlList.addAll(boyList);
        clazz.setUsers(girlList);
        clazz2.setUsers(girlList);
        //clazz stream
        Stream<Clazz> clazzSteam = Stream.of(clazz, clazz2);

        //clazz stream -> user stream 扁平化
        Stream<User> allUserStream = clazzSteam.flatMap(c -> c.getUsers().stream());
        System.out.println("兩個班級一共多少人:" + allUserStream.count());;
    }
}

//執行結果:

兩個班級一共多少人:40

####5.5 anyMatch

//是否存在x*x = 81的結果
boolean flag = Stream.of(1, 2, 4, 6, 3, 9, 7, 2, 4, 9, 7).map(x -> x * x).anyMatch(x -> x == 81);
System.out.println(flag);
//執行結果:true

####5.6 reduce Optional<T> reduce(BinaryOperator<T> accumulator) 這個方法的主要做用是把 Stream 元素組合起來,Optional使用方法,請參考網紅篇:Java函數式開發——優雅的Optional空指針處理

//clazz stream -> user stream
Stream<User> allUserStream = clazzSteam.flatMap(c -> c.getUsers().stream());
//串起全部名字 想了解optional用法能夠參考:http://my.oschina.net/chkui/blog/739034
Optional<String> names = allUserStream.
        map(User::getName).sorted((first, second) -> first.compareTo(second))
        .reduce((first, second) -> first + " *** " + second);
System.out.println(names.get());

執行結果:

boy0 *** boy0 *** boy1 *** boy1 *** boy2 *** boy2 *** boy3 *** boy3 *** boy4 *** boy4 *** boy5 *** boy5 *** boy6 *** boy6 *** boy7 *** boy7 *** boy8 *** boy8 *** boy9 *** boy9 *** girl0 *** girl0 *** girl1 *** girl1 *** girl2 *** girl2 *** girl3 *** girl3 *** girl4 *** girl4 *** girl5 *** girl5 *** girl6 *** girl6 *** girl7 *** girl7 *** girl8 *** girl8 *** girl9 *** girl9

####5.7 Parallel 並行運行 vs 普通stream操做

long startTime = System.nanoTime();

Map<String, List<Integer>> numbersPerThread = IntStream.rangeClosed(1, 100000)
        .parallel()
        .boxed()
        .collect(Collectors.groupingBy(i -> Thread.currentThread().getName()));
long runTime = System.nanoTime() - startTime;
System.out.println("運行時間:" + String.valueOf(runTime));
//運行時間:159695489
long startTime = System.nanoTime();

Map<String, List<Integer>> numbersPerThread = IntStream.rangeClosed(1, 100000)
        .boxed()
        .collect(Collectors.groupingBy(i -> Thread.currentThread().getName()));
long runTime = System.nanoTime() - startTime;
System.out.println("運行時間:" + String.valueOf(runTime));
//運行時間:94576511
相關文章
相關標籤/搜索