并发流

public class StreamTest01 {
    public static void main(String[] args) {
        Stream<String> s = Stream.of("hello", "hello", "world");
        //String collect = s.collect(Collectors.joining(",","《","》")); //《hello,hello,world》
        //toCollection
        //ArrayList<String> list = s.collect(Collectors.toCollection(() -> new ArrayList<>())); //[hello, hello, world]
        TreeSet<String> set = s.collect(Collectors.toCollection(TreeSet::new)); //[hello, world]
        System.out.println(set);
        //iterate
        List<Integer> x = Stream.iterate(2, item -> item + 2).limit(5).collect(Collectors.toList());// item==2    [2, 4, 6, 8, 10]

        //栗子:找出该流中大于2的元素,然后将每个元素乘以2,然后忽略掉流中的前两个质素,然后再取流中的前两个元素,最后求出流中元素的总和。
        Stream<Integer> stream = Stream.iterate(1, e -> e + 2).limit(6); //[1, 3, 5, 7, 9, 11]
        OptionalInt max = stream.filter(e -> e > 2).mapToInt(e -> e * 2).skip(2).limit(2).max();
        if (max.isPresent()) {
            System.out.println(max.getAsInt());
        }

        //流只能使用一次,每次中间操作都会产生一个新的流,供给下次操作

        //流是惰性求值,如果没有终止操作,只有中间操作,那么流就不会执行
        //如:
        List<String> list = Arrays.asList("ni", "hao");
         list.stream().map(
                 e->{
                     String upper=e.toUpperCase();
                     System.out.println("to upper");
                     return upper;
                 }
         );
        // 没有终止操作,map方法不会执行,上述代码不会打印任何东西


        list.stream().map(
                e->{
                    String upper=e.toUpperCase();
                    System.out.println("to upper");
                    return upper;
                }
        ).collect(Collectors.toList());
        // 打印:
        // to upper
        // to upper

    }
}

串行流和并行流对比:

public class StreamTest02 {
    public static void main(String[] args) {
        List<String> list=new ArrayList<>(5000000);

        for (int i = 0; i <5000000 ; i++) {
            list.add(UUID.randomUUID().toString());
        }

        System.out.println("串行流开始排序");
        long start = System.nanoTime();
        list.stream().sorted().count();
        long end = System.nanoTime();

        Long millis= TimeUnit.NANOSECONDS.toMillis(end-start);
        System.out.println("串行流用时"+millis+"毫秒");

        System.out.println("并行流开始排序");
        long s = System.nanoTime();
        list.parallelStream().sorted().count();
        long e = System.nanoTime();

        Long m= TimeUnit.NANOSECONDS.toMillis(e-s);
        System.out.println("并行流用时"+m+"毫秒");


    }
}

console:

串行流开始排序
串行流用时4707毫秒
并行流开始排序
并行流用时1852毫秒

Process finished with exit code 0

流的短路

注:如果一个流中有若干个操作,流的执行顺序并不是将第一个操作作用于所有元素,然后再将第二个操作作用于所有元素,以此类推,直至所有操作执行完(如果是这样的话,一个流中有多少个中间操作,元素就会被遍历多少次)。而是从第一个元素开始,执行完所有的操作,再到下一个元素执行完所有的操作,以此类推,遍历完所有的元素,所以,一个流执行完,共遍历了一次所有元素。

非短路操作

流的非短路操作:

就是所有的元素都遍厉完(但是单个元素在执行所有操作时,也可能发生短路而跳过后续操作,直接开始下一个元素),直到最后才结束.用来收集成自己想要的数据. 方法有: 遍厉 forEach 归约 reduce 最大值 max 最小值 min 聚合 collect 计数 count 遍厉 forEach

public class StreamTest03 {
    public static void main(String[] args) {

        List<Integer> words = Arrays.asList(6,4,6);

        long count = words.stream().filter(item -> {
                    System.out.println("-------------------------");
                    System.out.println("filter1:一次过滤大于4");
                    return item > 4;
                }
        ).filter(item -> {
                    System.out.println("filter2:二次过滤大于10");
                    return item < 10;
                }
        ).count();


    }
}



-------------------------
filter1:一次过滤大于4
filter2:二次过滤大于10
-------------------------
filter1:一次过滤大于4
-------------------------
filter1:一次过滤大于4
filter2:二次过滤大于10

Process finished with exit code 0

从打印语句可以看出,每个元素都挨个执行了操作,但是元素“4”,没有执行第二个filter,因为第一filter已经不满足,发生短路,不会再执行后续操作。

短路操作

类似于在Java中短路运算符”&&”(与) 和”||”

顾名思义,短路运算符具有短路功能. |-如果 “&&” 运算符的第一个表达式为false,则第二个表达式就不会执行 ,如果 “||” 运算符的第一个表达式为true,则第二个表达式就不会执行

流的一些操作也会短路,比如findfirst(),在流的执行过程中,如果发现一个符合所有操作的元素,则后续元素就不会再执行。

public class StreamTest03 {
    public static void main(String[] args) {

        List<Integer> words = Arrays.asList(2,6,7,6);

        words.stream().filter(item -> {
                    System.out.println("-------------------------");
                    System.out.println("filter1:一次过滤大于4");
                    return item> 4;
                }
        ).filter(item -> {
                    System.out.println("filter2:二次过滤大于5");
                    return item< 10;
                }
        ).map(item -> {
            System.out.println("map:当前元素为"+item);
            return item;
        }).findFirst();


    }
}


-------------------------
filter1:一次过滤大于4
-------------------------
filter1:一次过滤大于4
filter2:二次过滤大于5
map:当前元素为6

Process finished with exit code 0

可以看出,一共遍历了两个元素,后续元素被短路掉。