流式編程
流的一個核心好處是,它使得程序更加短小並且更易理解。
public class Demo1 { public static void main(String[] args) { new Random(47) // ints() 方法產生一個流並且 ints() 方法有多種方式的重載 // — 兩個參數限定了數值產生的邊界。這將生成一個整數流 .ints(5,60) .distinct()//distinct() 來獲取它們的非重復值 .limit(7)//使用 limit() 方法獲取前 7 個元素 .sorted()//使用 sorted() 方法排序 // forEach() 方法遍歷輸出,它根據傳遞給它的函數對每個 // 流對象執行操作。 .forEach(System.out::println); // 我們傳遞了一個可以在控制台顯示每個元素的方法引用。System.out::println } }
流操作的類型有三種:創建流,修改流元素(中間操作, Intermediate Operations),消費流元素(終端操作, Terminal Operations)。
創建流 public class BuildUp { public static void main(String[] args) { Stream.of("aaa","bbb","vvv").forEach(System.out::print); Stream.of(1111,2222,3333).forEach(System.out::print); //從 Map 集合中產生流數據,。然后分別調用 getKey() 和 getValue() 獲取值。 Map<String,Double> m = new HashMap<>(); m.put("AA",1.1); m.put("BB",1.3); m.put("DDD",3.1); m.put("CCC",2.1); //我們首先調用 entrySet() 產生一個對象流,每個對象都包含一個 key 鍵以及與其相關聯的 value 值 // 將對象作為e參數傳到后面, m.entrySet().stream().map(e -> e.getKey()+":"+ e.getValue()).forEach(System.out::println); } }
generate()
/* Supplier 接口有一個方法就是get */ public class Generate implements Supplier<String>{ Random rand = new Random(47); char[] letters = "ABCDEFGHIJK".toCharArray(); // 重寫接口中的函數,返回String類型值 public String get(){ // 在指定的數組里面挑選字母 // Random.nextInt() 的參數代表可以接受的最大的隨機數范圍 return "" + letters[rand.nextInt(letters.length)]; } public static void main(String[] args) { String word = Stream.generate(new Generate()).limit(20) .collect(Collectors.joining()); System.out.println(word); System.out.println("#######################"); Stream.generate(() -> "done").limit(3) .forEach(System.out::println); } }
Stream.iterate()
static <T> Stream<T> |
iterate(T seed, UnaryOperator<T> f)
返回有序無限連續
Stream 由函數的迭代應用產生
f 至初始元素
seed ,產生
Stream 包括
seed ,
f(seed) ,
f(f(seed)) ,等
|
以種子(第一個參數)開頭,並將其傳給方法(第二個參數)。方法的結果將添加到流,並存儲作為第一個參數用於下次調用 iterate()
Stream<T> |
skip(long n)
在丟棄流的第一個
n 元素后,返回由該流的
n 元素組成的流。
|
public class Fibonacci { int x =1; // 匿名函數 Stream<Integer> numbers(){ // lambada表達式的函數 return Stream.iterate(0,i ->{ int result = x +i; x = i; return result; }); } public static void main(String[] args) { new Fibonacci().numbers() .skip(10) .limit(10) .forEach(System.out::println); } } /* 斐波那契數列就是簽兩個數相加得到寫一個元素 55 89 144 233 377 610 987 1597 2584 418 */
流的建造者模式
static <T> Stream.Builder<T> |
builder()
返回一個
Stream 的構建器。
|
public class FileTo { // 建立構建器,builder Stream.Builder<String> builder = Stream.builder(); public FileTo(String fp) throws Exception{ Files.lines(Paths.get(fp)) .skip(1) // .forEach(line ->{for (String w:line.split("[ .?,]+"))//以上面做分割 builder.add(w);//分割完的部分加入流構建器里面 }); } Stream<String> stream(){ return builder.build(); } public static void main(String[] args) throws Exception { // 實例化流對象 new FileTo("src/flow/FileTo.java") .stream() .limit(7) .map(w -> w +" ") .forEach(System.out::print); } } /* import java nio file Files; import */
注意,構造器會添加文件中的所有單詞(除了第一行,它是包含文件路徑信息的注釋),但是其並沒有調用 build()
。只要你不調用 stream()
方法,就可以繼續向 builder
對象中添加單詞。
在該類的更完整形式中,你可以添加一個標志位用於查看 build()
是否被調用,並且可能的話增加一個可以添加更多單詞的方法。在 Stream.Builder
調用 build()
方法后繼續嘗試添加單詞會產生一個異常。
Arrays.stream()
Arrays
類中含有一個名為 stream()
的靜態方法用於把數組轉換成為流
public class Demo2 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("AAA"); list.add("BBB"); list.add("CCC"); list.add("DDD"); list.add("EEE"); System.out.println(list); list.stream().forEach(System.out::println); } }
stream()
同樣可以產生 IntStream,LongStream 和 DoubleStream。
public class IntLongDouble { public static void main(String[] args) { // int stream Arrays.stream(new int[] {1,2,3,4,5}) .forEach(n -> System.out.format("%d ",n));//lamabad表達式 System.out.println(); System.out.println("#######################"); //指定從哪里開始到哪里結束,左閉右開區間 Arrays.stream(new double[] {1.1,2.2,3.3,4.4,5.5,6.6,7.7},3,6) .forEach(n -> System.out.println(n)); System.out.println("##############"); Arrays.stream(new long[] {111111,444444,444999}) .forEach(System.out::println);//引用 } }
中間操作之跟蹤和調試