jdk1.8中使用Stream流

本文深入讲解Java 8中引入的Stream流,对比传统IO流,Stream流提供了更强大的功能和更简洁的语法,适用于大数据处理,减少IO操作,提高代码效率。文章详细介绍了Stream流的创建、常用操作如map、filter、flatMap等,并演示了如何使用Stream进行内部迭代和惰性求值,以及串行流和并行流的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是Stream流

这里说明一下,Stream流不像传统的java.io中的inputStream和outputStream流,在jdk8中Stream是对集合Connection的增强,Stream比传统的流更加的精炼,语法更加的简洁。

我们为什么使用Stream流

Stream流大大减少对io的频繁操作,并且有着非常不错的性能,连亚马逊对大量数据的分析也是用的Stream流,只需要写少量的代码就能实现功能,非常强大。

Stream流的入门

使用Stream进行外部迭代

public class StreamDemo1 {
    public static void main(String[]args){
        //外部迭代
        int [] nums = {1,2,3};
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        System.out.println("结果是:" + sum);

        //使用Strem进行内部迭代
        int sum2 = IntStream.of(nums).map( i -> i *2).sum();
        System.out.println("结果为:" + sum2);

        System.out.println("惰性求值是终止没有调用的情况下,中间的操作不会执行");

        IntStream.of(nums).map(StreamDemo1::doubNum);
    }

    public  static int doubNum(int i){
        System.out.println("执行了乘以二");
        return i * 2;
    }
}

使用Stream流的内部迭代

int sum2 = IntStream.of(nums).map(i -> i*2).num;//使用了Stream的外部迭代
System.out.println("num:" + sum2);

惰性求值

IntStream.of(nums).map(StreamDemo1::doubNum);//这个就是惰性求值

注意:惰性求值是终止没有调用的情况下,中间的操作不会执行

Stream流的创建

从集合中创建

List<String> list = new ArrayList<String>();
list.stream();
list.parallelStream();//创建并行流

数字流

IntStream.of(1,2,3);
IntStream.rangeClosed(1,10);

从数组总创建

Arrays.Stream(new [] int {1,2,3})

通过随机数创建无线流

new Random.ints().limit(10);

自己产生流

Stream.generate(()-> r.nextInt()).limit(20).forEach(System.out::println);

完整代码

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

        //从集合中创建
        list.stream();
        list.parallelStream();

        //从数组中创建
        Arrays.stream(new int [] {1,2,3});

        //使用rondom创建无线流
        new Random().ints().limit(10);

        //创建数字流
        IntStream.of(1,2,3);
        IntStream.rangeClosed(1,10);
        Random r = new Random();

        //自己产生流
        Stream.generate(()-> r.nextInt()).limit(20).forEach(System.out::println);
    }
}

Strem流中常用的几个方法

完整例子

public class StreamDemo3 {
    public static void main(String[]args){
        String str = "i want to be a software enginner";
        
        Stream.of(str.split(" ")).map( s -> s.length()).forEach(System.out::println);

        Stream.of(str.split(" ")).filter(s -> s.contains("a")).map(s -> s.length()).forEach(System.out::println);

        Stream.of(str.split(" ")).flatMap(s -> str.chars().boxed()).forEach(i -> System.out.println((char)i.intValue()));

        Stream.of(str.split(" ")).peek(System.out::println).forEach(System.out::println);

        //limit 使用 ,主要用于无线流
        new Random().ints().filter(i -> i > 100 && i < 1000).limit(10).forEach(System.out::println) ;
        
    }
}

map

Stream.of(str.split(" ")).map( s -> s.length()).forEach(System.out::println);

这句代码的意思将字符串str进行分割 得到完整的单词,然后在将每个单词的长度进行遍历输出

filter

Stream.of(str.split(" ")).filter(s -> s.contains("a")).map(s -> s.length()).forEach(System.out::println);

这句代码的意思将字符串分割后,得到完整的单词并且打印只包含a的单词的长度

flatMap

Stream.of(str.split(" ")).flatMap(s -> str.chars().boxed()).forEach(i -> System.out.println((char)i.intValue()));

这句话的意思是将字符串分割后得到完整的单词并且扁平化进行遍历输出

limit主要用于无线流

new Random().ints().filter(i -> i > 100 && i < 1000).limit(10).forEach(System.out::println) ;

流的操作二

完整例子

public class StreamDemo4 {
    public static void main(String[]args){
        String str = "hello lambda hello";

        //使用并行流
        str.chars().parallel().forEach( s -> System.out.println((char)s));
        //保证顺序
        str.chars().parallel().forEachOrdered(i -> System.out.println((char)i));

        //收集器
        List<String> list = Stream.of(str.split(" ")).collect(Collectors.toList());
        System.out.println("这是一个list:" + list);

        //使用reduce拼接字符串
        Optional<String> letters = Stream.of(str.split(" ")).reduce((s1,s2) -> s1 + "|" + s2);

        System.out.println(letters.orElse(""));

        //计算所有单词总长度
        Integer lent = Stream.of(str.split(" ")).map(s -> s.length()).reduce(0,(s1,s2) -> s1 + s2);

        System.out.println("单词的总长度是:" + lent);

        //max
        Optional<String> max = Stream.of(str.split(" ")).max((s1,s2) -> s1.length() - s2.length());
        System.out.println("单词最长的是:" + max.get());

        OptionalInt findFirst =  new Random().ints().findFirst();
        System.out.println("短路操作" + findFirst.getAsInt());

        IntPredicate intPredic =  null;
        boolean allMath = new Random().ints().allMatch(intPredic);
        System.out.println("allmath:" + allMath);
    }

需要注意的是下面这中操作是不会保证顺序的

str.chars().parallel().forEach( s -> System.out.println((char)s));

如果想要保证顺序那么使用下面这种方法

 str.chars().parallel().forEachOrdered(i -> System.out.println((char)i));

forEachOrdered 会按照顺序进行输出

串行流和并行流以及线程池

完整的demo

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

        IntStream.range(1,100).parallel().peek(StreamDemo5::debug).count();

        //parallel 并行流
        IntStream.range(1,100).parallel().peek(StreamDemo5::debug).
                //sequential串行流
                sequential().peek(StreamDemo5::debug2).count();

        ForkJoinPool pool = new ForkJoinPool(20);
        pool.submit(() -> IntStream.range(1,100).parallel().peek(StreamDemo5::debug).count());
        pool.shutdown();

        synchronized (pool){
            try {
                pool.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //让自己的线层池,不使用默认线程池,防止任务被阻塞


    public static void debug(int i){
        System.out.println("debug" + i);
        System.out.println("线程" + Thread.currentThread().getName()  + ":" + i);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void debug2(int i){
        System.err.println("debug" + i);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

这里需要注意的是,ForkJoinPool是jdk默认提供的线程池,利用这个线程池可以将大任务,拆分成小任务,但是可能会发生线程的阻塞。

 public static void debug(int i){
        System.out.println("debug" + i);
        System.out.println("线程" + Thread.currentThread().getName()  + ":" + i);
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

我们可以使用自己的线程池,来防止线程被阻塞。

总结

Stream流有很多很有用的方法,比起传统的io流,它显的更加强大,代码更简洁,在配合lambda表达式简直就是如虎添翼。我更希望大家去学习Stream流。

Stream是在Java 8之后新增的一个特性,它是用来操作集合(Collection)的工具。Stream提供了一种简洁、高效的方式来对集合进行处理和操作。Stream可以用于遍历集合中的元素、进行过滤、映射、排序、聚合等各种操作。 在使用Stream时,常用的方法之一是forEach()方法,它用来遍历Stream中的数据。这个方法是一个终结方法,一旦调用了forEach()方法,就不能再继续调用Stream中的其他方法了。例如,下面的代码演示了如何使用forEach()方法遍历一个Stream并打印其中的元素: ``` List<String> list = Arrays.asList("字节","网易","百度", "美团", "阿里", "字节"); Stream<String> stream = list.stream(); stream.forEach(System.out::println); ``` 执行以上代码会依次打印出集合中的元素:"字节"、"网易"、"百度"、"美团"、"阿里"、"字节"。 除了forEach()方法之外,Stream还提供了许多其他常用的方法,比如filter()用于过滤元素、map()用于映射元素、sorted()用于排序元素、reduce()用于聚合元素等等。这些方法可以根据具体的需求来选择使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [JDK1.8常见的Stream](https://blog.csdn.net/TFHoney/article/details/129687717)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值