package net.codingme.feature.jdk8; import org.junit.Test; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; /** * <p> * JDK 8 steam 流操做 * * @Author niujinpeng * @Date 2019/8/12 18:03 */ public class Jdk8Stream { /** * 建立流的幾種方式 * 集合 * Collection.stream(); * Collection.parallelStream() * 數組 * Arrays.stream(T array) or Stream.of() * 文件流 * java.io.BufferedReader.lines() * 靜態方法 * IntStream.range,IntStream.of */ @Test public void createStream() throws FileNotFoundException { List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"); String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"}; // 集合獲取 Stream 流 Stream<String> nameListStream = nameList.stream(); // 集合獲取並行 Stream 流 Stream<String> nameListStream2 = nameList.parallelStream(); // 數組獲取 Stream 流 Stream<String> nameArrStream = Stream.of(nameArr); // 數組獲取 Stream 流 Stream<String> nameArrStream1 = Arrays.stream(nameArr); // 文件流獲取 Stream 流 BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md")); Stream<String> linesStream = bufferedReader.lines(); // 從靜態方法獲取流操做 IntStream rangeStream = IntStream.range(1, 10); rangeStream.limit(10).forEach(num -> System.out.print(num+",")); System.out.println(); IntStream intStream = IntStream.of(1, 2, 3, 3, 4); intStream.forEach(num -> System.out.print(num+",")); } @Test public void streamDemo(){ List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"); // 1. 篩選出名字長度爲4的 // 2. 名字前面拼接 This is // 3. 遍歷輸出 nameList.stream() .filter(name -> name.length() == 4) .map(name -> "This is "+name) .forEach(name -> System.out.println(name)); } /** * 轉換成爲大寫而後收集結果,遍歷輸出 */ @Test public void toUpperCaseDemo() { List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"); List<String> upperCaseNameList = nameList.stream() .map(String::toUpperCase) .collect(Collectors.toList()); upperCaseNameList.forEach(name -> System.out.print(name + ",")); } /** * 把數字值乘以2 */ @Test public void mapTest() { List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); // 映射成 2倍數字 List<Integer> collect = numberList.stream() .map(number -> number * 2) .collect(Collectors.toList()); collect.forEach(number -> System.out.print(number + ",")); System.out.println(); numberList.stream() .map(number -> "數字 " + number + ",") .forEach(number -> System.out.print(number)); } /** * flatmap把對象扁平化 */ @Test public void flatMapTest() { Stream<List<Integer>> inputStream = Stream.of( Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6) ); List<Integer> collect = inputStream .flatMap((childList) -> childList.stream()) .collect(Collectors.toList()); collect.forEach(number -> System.out.print(number + ",")); } /** * 遍歷輸出 */ @Test public void forEachTest(){ List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); numberList.stream().forEach(number -> System.out.print(number+",")); } /** * filter 數據篩選 * 篩選出偶數數字 */ @Test public void filterTest() { List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); List<Integer> collect = numberList.stream() .filter(number -> number % 2 == 0) .collect(Collectors.toList()); collect.forEach(number -> System.out.print(number + ",")); } /** * 查找第一個數據 * 返回的是一個 Optional 對象 */ @Test public void findFirstTest(){ List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); Optional<Integer> firstNumber = numberList.stream() .findFirst(); System.out.println(firstNumber.orElse(-1)); } /** * Stream 轉換爲其餘數據結構 */ @Test public void collectTest() { List<Integer> numberList = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5); // to array Integer[] toArray = numberList.stream() .toArray(Integer[]::new); // to List List<Integer> integerList = numberList.stream() .collect(Collectors.toList()); // to set Set<Integer> integerSet = numberList.stream() .collect(Collectors.toSet()); System.out.println(integerSet); // to string String toString = numberList.stream() .map(number -> String.valueOf(number)) .collect(Collectors.joining()).toString(); System.out.println(toString); // to string split by , String toStringbJoin = numberList.stream() .map(number -> String.valueOf(number)) .collect(Collectors.joining(",")).toString(); System.out.println(toStringbJoin); } /** * 使用流操做和不使用流操做的編碼風格對比 */ @Test public void diffTest() { // 不使用流操做 List<String> names = Arrays.asList("Jack", "Jill", "Nate", "Kara", "Kim", "Jullie", "Paul", "Peter"); // 篩選出長度爲4的名字 List<String> subList = new ArrayList<>(); for (String name : names) { if (name.length() == 4) { subList.add(name); } } // 把值用逗號分隔 StringBuilder sbNames = new StringBuilder(); for (int i = 0; i < subList.size() - 1; i++) { sbNames.append(subList.get(i)); sbNames.append(", "); } // 去掉最後一個逗號 if (subList.size() > 1) { sbNames.append(subList.get(subList.size() - 1)); } System.out.println(sbNames); System.out.println("----------------"); // 使用 Stream 流操做 String nameString = names.stream() .filter(num -> num.length() == 4) .collect(Collectors.joining(", ")); System.out.println(nameString); // String string = names.stream().filter(num -> num.length() == 4).map(name -> name.toUpperCase()).collect(Collectors.joining(",")); String string = names.stream() .filter(num -> num.length() == 4) .map(name -> name.toUpperCase()) .collect(Collectors.joining(",")); } /** * reduce 字符串拼接例子 */ @Test public void reduceTest() { List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python"); String s = skills.stream().reduce((all, skill) -> all + skill).get(); System.out.println(s); } /** * 數據去重例子 */ @Test public void distinctTest() { List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python", "java"); List<String> collects = skills.stream().distinct().collect(Collectors.toList()); collects.forEach(skill -> System.out.println(skill)); System.out.println("---------------------------------------------"); skills = Arrays.asList("java", "golang", "c++", "c", "python", "java"); skills.stream().distinct().forEach(s -> System.out.println(s)); } /** * 數學計算測試 */ @Test public void mathTest() { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6); IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics(); System.out.println("最小值:" + stats.getMin()); System.out.println("最大值:" + stats.getMax()); System.out.println("個數:" + stats.getCount()); System.out.println("和:" + stats.getSum()); System.out.println("平均數:" + stats.getAverage()); } /** * 按年齡分組 */ @Test public void groupByTest() { List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26); Map<String, List<Integer>> ageGrouyByMap = ageList.stream() .collect(Collectors.groupingBy(age -> String.valueOf(age / 10))); ageGrouyByMap.forEach((k, v) -> { System.out.println("年齡" + k + "0多歲的有:" + v); }); } /** * 按某個條件分組 * 給一組年齡,分出成年人和未成年人 */ @Test public void partitioningByTest() { List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26); Map<Boolean, List<Integer>> ageMap = ageList.stream() .collect(Collectors.partitioningBy(age -> age > 18)); System.out.println("未成年人:" + ageMap.get(false)); System.out.println("成年人:" + ageMap.get(true)); } /** * 生成本身的 Stream 流 */ @Test public void generateTest(){ // 生成本身的隨機數流 Random random = new Random(); Stream<Integer> generateRandom = Stream.generate(random::nextInt); generateRandom.limit(5).forEach(System.out::println); // 生成本身的 UUID 流 Stream<UUID> generate = Stream.generate(UUID::randomUUID); generate.limit(5).forEach(System.out::println); } /** * 獲取 / 扔掉前 n 個元素 */ @Test public void limitOrSkipTest() { // 生成本身的隨機數流 List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26); ageList.stream() .limit(3) .forEach(age -> System.out.print(age+",")); System.out.println(); ageList.stream() .skip(3) .forEach(age -> System.out.print(age+",")); } /** * 找出偶數 */ @Test public void lazyTest() { // 生成本身的隨機數流 List<Integer> numberLIst = Arrays.asList(1, 2, 3, 4, 5, 6); // 找出第一個偶數 Stream<Integer> integerStream = numberLIst.stream() .filter(number -> { int temp = number % 2; if (temp == 0 ){ System.out.println(number); } return temp == 0; }); System.out.println("分割線"); List<Integer> collect = integerStream.collect(Collectors.toList()); } /** * 並行計算 */ @Test public void main() { // 生成本身的隨機數流,取一千萬個隨機數 Random random = new Random(); Stream<Integer> generateRandom = Stream.generate(random::nextInt); List<Integer> numberList = generateRandom.limit(10000000).collect(Collectors.toList()); // 串行 - 把一千萬個隨機數,每一個隨機數 * 2 ,而後求和 long start = System.currentTimeMillis(); int sum = numberList.stream().map(number -> number * 2).mapToInt(x -> x).sum(); long end = System.currentTimeMillis(); System.out.println("串行耗時:"+(end - start)+"ms,和是:"+sum); // 並行 - 把一千萬個隨機數,每一個隨機數 * 2 ,而後求和 start = System.currentTimeMillis(); sum = numberList.parallelStream().map(number -> number * 2).mapToInt(x -> x).sum(); end = System.currentTimeMillis(); System.out.println("並行耗時:"+(end - start)+"ms,和是:"+sum); } @Test public void simpleTest(){ List<Integer> numbers = Arrays.asList(1, 2, 3); int[] factor = new int[] { 2 }; Stream<Integer> stream = numbers.stream() .map(e -> e * factor[0]); factor[0] = 0; stream.forEach(System.out::println); } }