public class StreamMethods { /** * 流的過濾 * 大部分流操做的結果仍然是一個流,因此咱們能夠鏈式調用 */ public void testStreamFilter() { List<Integer> integers = new ArrayList<>(); integers.addAll(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)); //使用流類庫 integers = integers.stream().filter(i -> i > 5).collect(Collectors.toList()); System.out.println(integers); } /** * 流的映射 * 相似於SQL中的select,能夠將一組元素轉換成另外一種元素。 * 下面的例子將一組整數轉換爲平方。這是一個簡單的例子,實際場合中經常須要將一組對象流轉換爲另外一組對象。 */ public void testStreamMap() { List<Integer> integers = Stream.of(1, 2, 3, 4) .map(i -> i * i) .collect(Collectors.toList()); System.out.println(integers); } /** * 流的平整映射 * 有時候須要將多個流的結果合併爲一個流,這時候須要使用平整映射。 */ public void testStreamFlatMap() { List<Integer> integers = Stream.of(Arrays.asList(1, 2, 3, 4), Arrays.asList(5, 6)) .flatMap(n -> n.stream()) .collect(Collectors.toList()); System.out.println(integers); } /** * 流求最大或最小值 */ public void testStreamMaxOrMin() { int min = Stream.of(1, 23, 4, 50, 8888) .min(Comparator.comparingInt(i -> i)) .get(); int max = Stream.of(0, 1, 2, 5, 89, 465, 45, 666, 8888) .max(Comparator.comparingInt(i -> i)).get(); System.out.println(String.format("max:%d,min:%d", max, min)); } /** * TODO 不太懂這個接口 流的通用迭代 reduce */ public void testStreamReduce() { int sum = Stream.of(1, 2, 3, 4, 5) .reduce((acc, e) -> acc + e).get(); System.out.println(String.format("sum:%d", sum)); int product = Stream.of(1, 2, 3, 4, 5) .reduce(1, (acc, e) -> acc * e); System.out.println(String.format("product:%d", product)); } /** * 流的一些謂詞特性 * allMatch:當全部條件知足時返回true * anyMatch:只要有一個元素知足就返回true * noneMatch:當沒有元素返回時返回true * distinct:去掉重複的元素 * limit:保留流的前幾個元素 * skip:跳過前幾個元素而獲取以後的全部元素 */ public void testStreamPredicate() { boolean allMatch = Stream.of(1, 2, 3, 4, 5).allMatch(i -> i > 3); System.out.println("allMatch: " + allMatch); boolean anyEqual = Stream.of(1, 2, 3, 4, 5).anyMatch(i -> i >= 2); System.out.println("anyMatch: " + anyEqual); boolean noneEqual = Stream.of(1, 2, 3, 4, 5).noneMatch(i -> i < 0); System.out.println("noMatch: " + noneEqual); List<Integer> list = Stream.of(1, 2, 3, 4, 2, 2, 4, 3, 1, 2, 4, 3, 1, 2) .distinct() .collect(Collectors.toList()); System.out.println(list); String list1 = Stream.of(1, 2, 3, 4, 5, 6) .limit(3) .map(String::valueOf) .collect(Collectors.joining(", ", "[", "]")); System.out.println(list1); String list2 = Stream.of(1, 2, 3, 4, 5, 6) .skip(3) .map(String::valueOf) .collect(Collectors.joining(", ", "[", "]")); System.out.println(list2); } /** * 基本類型流 * 因爲Java存在一個基本類型裝箱拆箱的過程,因此會有性能開銷。 * 爲了不這些開銷,流類庫針對常見的基本類型int、long、double作了特殊處理, * 爲它們單獨準備了一些類和方法。 * 注意:對於一些方法也有基本類型的版本,能夠將一個對象流轉換爲對應的基本類型, * 這些方法的命名規則是方法名+To+基本類型。若是須要處理大量數據的基本類型流, * 能夠考慮使用這些方法。 */ public void testStreamPrimitiveType() { IntStream intStream = IntStream.of(1, 2, 3, 4, 5); LongStream longStream = LongStream.of(1, 2, 3, 4, 5); DoubleStream doubleStream = DoubleStream.of(10, 2.0, 3.0); int sum = Stream.of(1, 2, 3, 4, 5) .mapToInt(i -> i) .reduce(0, (acc, e) -> acc + e); //.sum(); System.out.println("sum :" + sum); } /** * 流的收集器(collect()方法) * 使用流類庫的最後一步就是將流轉換爲咱們須要的集合了,這就須要用到收集器。 * 收集數據的最後一步須要調用collect方法,它的參數是java.util.stream.Collector類的靜態方法。 * 聽起來是否是有點奇怪,實際上,接受的是這些方法的返回值。 * 例如toList()方法其實是這樣的,返回的是Collector對象,而後由collect方法處理,獲取最後的集 * 合。 * 源代碼示例 * public static <T>Collector<T, ?, List<T>> toList() { * return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, * (left, right) -> { left.addAll(right); return left; }, * CH_ID); * } */ /** * 經過收集器得到流的集合 */ public void testGetStreamCollections(){ List<Integer> integers = Stream.of(1,2,3,4,5) .collect(Collectors.toList()); System.out.println("list: "+integers); Set<Integer> set = Stream.of(1,2,2,3,4,5) .collect(Collectors.toSet()); System.out.println("set: "+set); //使用本身但願的集合(能夠構形成map集合或concurrentMap集合) ArrayList<Integer> integerArrayList = Stream.of(1,2,3) .collect(Collectors.toCollection(ArrayList::new)); System.out.println("integerArrayList: "+integerArrayList); } /** * 經過收集器獲取流的值 * 收集器不只能夠得到集合,還能夠由流獲取一個值, * 這能夠經過調用maxBy、minBy、averageXXX和summingXXX方法來實現 */ public void testGetStreamValue(){ int max = Stream.of(1,2,3,4) .collect(Collectors.maxBy(Comparator.comparing(i->i))) .get(); int min = Stream.of(1,2,3,4) .collect(Collectors.minBy(Comparator.comparing(i->i))) .get(); double average = Stream.of(1,2,3,4) .collect(Collectors.averagingInt(Integer::intValue)); int sum = Stream.of(1,2,3,4) .collect(Collectors.summingInt(i->i)); System.out.println( String.format("max:%d,min:%d,average:%f,sum:%d", max, min, average, sum)); /** * 有時候須要將流的數據組合爲一個字符串,這須要joining收集器,它的三個參數分別是分隔符、前綴和後綴。 * 固然因爲它須要字符序列,因此這裏還須要用map方法將整數流轉換爲字符串流。 */ String string = Stream.of(1,2,3,4,5) .map(String::valueOf) .collect(Collectors.joining(", ","[","]")); System.out.println("string :"+string); /** * 還有一個簡單的收集器,做用就是計數,須要注意的是計數返回的結果是long類型就好了。 * 這個收集器的主要做用是和其餘收集器一塊兒完成複雜的功能。 */ Long count = Stream.of(1,2,3,4,5,6,7,8) .collect(Collectors.counting()); // .count(); System.out.println("count: "+count); } /** * 流的數據分塊 */ public void testStreamDataPartition() { Map<Boolean, List<Integer>> map = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) .collect(Collectors.partitioningBy(i -> i % 2 == 0)); System.out.println("map: " + map); } /** * 流的數據分組 * 相似於SQL中的group by語句。下面的例子將流按照數組個位數分爲好幾組 */ public void testDataGrouping() { Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22) .collect(Collectors.groupingBy(i -> i % 10)); System.out.println("map: "+map); } /** * 流的組合收集器 * 若是問題比較複雜,還能夠將多個收集器組合起來使用,一些收集器有重載的版本,支持第二個收集器, * 能夠用來實現這個功能。就拿前面那個數據分組的例子來講,此次我不只要分組, * 並且只須要每組的十位數字,那麼就能夠這樣寫。 * groupingBy的第二個參數可使用mapping收集器,mapping這裏的做用和流操做的map相似, * 將流再次進行映射,而後收集結果做爲最後Map的鍵值對。 */ public void testGroupCollect(){ //按個位數字進行分組,而後只獲取十位上的數字 Map<Integer, List<Integer>> map = Stream.of(21, 32, 43, 54, 11, 33, 22) .collect(Collectors.groupingBy(i -> i % 10, Collectors.mapping(i -> i / 10,Collectors.toList()))); System.out.println("map: "+map); //按個位數字分組,而後而後求各組的和 Map<Integer,Integer> map1 = Stream.of(21,32,43,54,11,33,22) .collect(Collectors.groupingBy(i->i%10,Collectors.summingInt(i->i))); System.out.println("map1: "+map1); } /** * 關於流的其它特性 */ public void testOther(){ /** * * 全部的流操做都是惰性的,也就是說直到最後調用收集器的時候,整個流操做纔開始進行。 * 在這以前,你的流操做只不過相似於SQL的執行計劃,這時候尚未真正執行程序。因此下面的代碼什麼都不會輸出。 */ Stream.of(1,2,3,4,5) .filter(i->i>1) .filter(i->{ System.out.println("i: "+i); return i<=3; }); /** * 若是進行了不少流操做,流類庫會不會對流進行屢次迭代,致使程序速度很慢呢? * 這個擔憂也是多餘的,流類庫通過優化,會保證迭代以最少的次數進行。 * 因此下面的代碼輸出結果是122334455,這說明流只迭代了一次。 */ List<Integer> integers = Stream.of(1, 2, 3, 4, 5) .filter(i -> { System.out.print(i); return i > 1; }) .filter(i -> { System.out.print(i); return i <= 3; }) .collect(Collectors.toList()); System.out.println(integers); } /** * 流的循環 */ public void testForLoop(){ /** * 流的循環,至關於for循環 */ IntStream.range(0, 3) .forEach(i -> System.out.print(i)); } /** * 流的數據並行化 * 須要注意並非說並行化以後,速度就必定會比串行化快, * 這須要根據當前系統、機器、執行的數據流大小來進行綜合評估。 * ArrayList這類容器就比較容易並行化,而HashMap並行化就比較困難。 */ public void testStreamParallel(){ List<Integer> integers = IntStream.range(1, 101) .parallel() .filter(i -> i % 2 == 0) .boxed() .collect(Collectors.toList()); System.out.println("integers :"+integers); } }