Stream流

Stream流的作用:

结合了Lambda表达式,简化集合,数组操作

使用步骤:

  1. 先得到一条Stream流(流水线),并把数据放上去。
  2. 使用中间方法对流水线上的数据进行操作。
  3. 使用终结方法对流水线上的数据进行操作。
获取方式 方法名 说明
单列集合 default Stream stream() Collection 中的默认方法
双列集合 无法直接使用 stream 流
数组 public static Stream stream(T[] array) Arrays 工具类中的静态方法
一堆零散数据 public static Stream of(T... values) Stream 接口中的静态方法

 双列集合无法直接使用Stream流,可以使用keySet(),和entrySet()方法 

下面举四个例子来分别解释单列集合,双列集合,数组,一堆零散数据

Stream流中的foreach方法

在Java的Stream API中,forEach方法用于对Stream中的每个元素执行指定的操作。它是一个终端操作,意味着调用forEach后会关闭流,无法再进行其他操作。

forEach方法接收一个Consumer函数式接口作为参数,该接口接受一个输入参数并返回void。通常用于遍历流中的元素并执行某些操作,例如打印或修改元素。

List list = Arrays.asList("a", "b", "c");
list.stream().forEach(System.out::println);

与for-each循环的区别

虽然forEach方法与传统的for-each循环都可以用于遍历集合,但它们有一些不同之处。forEach是Stream API的一部分,适用于流式处理,而for-each循环是Java语言的基础语法。

并行流中的forEach

在并行流中,forEach方法的执行顺序是不确定的,因为元素可能被多个线程并发处理。如果需要保持顺序,可以使用forEachOrdered方法。

List list = Arrays.asList("a", "b", "c");
list.parallelStream().forEachOrdered(System.out::println);

注意事项

forEach方法通常用于执行副作用操作(如打印或修改外部状态),而不是用于生成新的流或集合。如果需要生成新的流或集合,应使用mapfilter等方法。

总结

forEach方法是Stream API中用于遍历元素的便捷工具,适用于需要对每个元素执行操作的场景。但在并行流中使用时需注意顺序问题,并且应避免将forEach用于生成新流或集合的操作。

Stream流的思想和获取Stream流:

单列集合:    

单列集合:default Stream stream()    Collection 中的默认方法

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Collections;

public class StreamDemo1 {
    public static void main(String[] args) {
//        获取方式	方法名	说明
//        单列集合	default Stream stream()	Collection 中的默认方法
//        双列集合	无	无法直接使用 stream 流
//        数组	public static  Stream stream(T[] array)	Arrays 工具类中的静态方法
//        一堆零散数据	public static Stream of(T... values)	Stream 接口中的静态方法
        ArrayList list = new ArrayList<>();
        Collections.addAll(list,"e","b","c","d");
////        获取一条流水线并把集合中的数据放在流水线中
//        Stream stream = list.stream();
////        使用终结方法打印流水线上的所有数据
//        stream.forEach(new Consumer() {
//            @Override
//            public void accept(String s) {
////                s:依次表示流水线上的每一个数据
//                System.out.println(s);
//            }
//        });

        list.stream().forEach(s->System.out.println(s));
    }

}

双列集合    

 双列集合    无    无法直接使用 stream 流

package com.itheima.demo1;

import java.util.HashMap;

public class StreamDemo3 {
    public static void main(String[] args) {
        //        双列集合	无	无法直接使用 stream 流

//        双列集合不能直接使用Stream流,需要转换

//        创建双列集合
        HashMap hm=new HashMap<>();
//        添加数据
        hm.put("a",1);
        hm.put("b",2);
        hm.put("c",3);
        hm.put("d",4);
//      第一种获取Stream流
//        hm.keySet().stream().forEach(s->System.out.println(s));
//      第二种获取Stream流的方法
//        hm.values().stream().forEach(s->System.out.println(s));

    }
}

数组 

数组    public static Stream stream(T[] array)    Arrays 工具类中的静态方法

package com.itheima.demo1;

import java.util.Arrays;

public class StreamDemo4 {
    public static void main(String[] args) {
        //        数组	public static  Stream stream(T[] array)	Arrays 工具类中的静态方法

//      1.创建数组
        int[] a = {1,2,3,4,5,6,7,8,9,10};

        String[] b={"a","b"};
//       2.获取Stream流方法
        Arrays.stream(a).forEach(s->System.out.print(s));

        System.out.println();
        System.out.println("========================");

        Arrays.stream(b).forEach(s->System.out.print(s));
    }
}

一堆零散数据

一堆零散数据    public static Stream of(T... values)    Stream 接口中的静态方法

package com.itheima.demo1;

import java.util.stream.Stream;

public class StreamDemo5 {
    public static void main(String[] args) {
//        一堆零散数据	public static Stream of(T... values)	Stream 接口中的静态方法
//        零散数据必须是同一个类型
//            Stream.of(1,2,3,4).forEach(s->System.out.print(s));
//            System.out.println();
//            Stream.of("a","b","c","d").forEach(s->System.out.print(s));
            String[] w={"a","b","c"};
            //这样写其实是错误的,引用数据类型打印出来的是数据,基本数据类型打印出来的是地址值,会把基本数据类型当作一个元素放到Stream中
            Stream.of(w).forEach(s->System.out.print(s));
    }
}

 Stream流的中间方法:

名称 说明
Stream filter(Predicate predicate) 过滤
Stream limit(long maxSize) 获取前几个元素
Stream skip(long n) 跳过前几个元素
Stream distinct() 元素去重,依赖hashCodeequals方法
static Stream concat(Stream a, Stream b) 合并ab两个流为一个流
Stream map(Function mapper) 转换流中的数据类型

注意1: 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程

注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据

filter:

过滤:可以加条件

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Collections;

public class StreamDemo6 {
    public static void main(String[] args) {
//        Stream filter(Predicate predicate)	过滤
//        Stream limit(long maxSize)	获取前几个元素
//        Stream skip(long n)	跳过前几个元素
//        Stream distinct()	元素去重,依赖hashCode和equals方法
//        static  Stream concat(Stream a, Stream b)	合并a和b两个流为一个流
//        Stream map(Function mapper)	转换流中的数据类型
        ArrayList list = new ArrayList<>();

        Collections.addAll(list,"张无忌","周大力","张三丰","张三");
//        filter 过滤 把姓张的留下来
//        list.stream().filter(new Predicate() {
//            @Override
//            public boolean test(String s) {
////                如果返回值为true表示当前数据留下来
////                如果返回值为false表示当前数据舍弃不要
//                return s.startsWith("张");
//            }
//        }).forEach(s->System.out.println(s));

//        改进:list.stream().filter(s->s.startsWith("张"))返回的是Stream流,中间方法返回的是Syteam流,中间方法返回后就会关闭,所以说建议使用链式方程,因为只使用一次
        list.stream()
                .filter(s->s.startsWith("张"))
                .forEach(s->System.out.println(s));
        System.out.println();
        //可以看出来Stream流没有改变集合数据
        System.out.println(list);

    }
}

 limit和skip:

limit:限制前n个元素

skip:跳过前n个元素

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Collections;

public class StreamDemo7 {
    public static void main(String[] args) {
//        Stream limit(long maxSize)	获取前几个元素
//         Stream skip(long n)	跳过前几个元素
        ArrayList list = new ArrayList<>();
        Collections.addAll(list,"张无忌","周大力","张三丰","张三","张良","王二麻子","谢广坤");
//        limit   获取前几个元素
//        skip    跳过前几个元素

//        "张无忌","周大力","张三丰","张三","张良","王二麻子","谢广坤"
        list.stream().limit(3)
                .forEach(s -> System.out.println(s));//打印就知道就获取了前三个
                System.out.println("");
        list.stream().skip(4)
                .forEach(s -> System.out.println(s));//跳过前三个,从第四个开始
        System.out.println("");
        list.stream().skip(2).limit(3).forEach(s -> System.out.println(s));
    }
}

distinct和concat:

        distinct   元素去重,依赖(hashcode和equqls方法)
        concat    合并a和b两个流为一个流

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;

public class StreamDemo8 {
    public static void main(String[] args) {
//        distinct   元素去重,依赖(hashcode和equqls方法)
//        concat    合并a和b两个流为一个流
        ArrayList list = new ArrayList<>();
        Collections.addAll(list,"张无忌","张无忌","周大力","张三丰","张三","张良","王二麻子","谢广坤");

        ArrayList list2 = new ArrayList<>();
        Collections.addAll(list2,"燕知春","秦叮咚","楚天秋","齐夏");

        //在这里是需要重写hashcode和equqls方法的不过String已经帮我们重写了
        list.stream().distinct().forEach(s->System.out.println(s));

        //        concat    合并a和b两个流为一个流(数据类型必须一样)

        Stream.concat(list.stream(),list2.stream()).distinct().forEach(s->System.out.println(s));
    }
}

   map:

       Stream map(Function mapper)    转换流中的数据类型

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;

public class StreamDemo9 {
    public static void main(String[] args) {
        //        Stream map(Function mapper)	转换流中的数据类型

        ArrayList list2 = new ArrayList<>();
        Collections.addAll(list2,"燕知春-20","秦叮咚-21","楚天秋-24","齐夏-19");
//       需求:只获取里面的年龄并进行打印

//        下面的第一个类型是本来的,String
//        第二个是要转成的数据类型,Integer

        //当map执行完毕后流上的数据就变成了整数
        list2.stream().map(new Function() {
            @Override
            public Integer apply(String s) {
                String[] split = s.split("-");
                String age = split[1];
                return Integer.parseInt(age);//转换成整数
            }
        }).forEach(s->System.out.println(s));

        System.out.println();

        list2.stream()
                .map(s->Integer.parseInt(s.split("-")[1]))
                .forEach(s->System.out.println(s));
    }
}

 Stream中的终结方法:

名称 说明
void forEach(Consumer action) 对 Stream 中的每个元素执行指定的Consumer动作,用于遍历流中的元素 。
long count() 返回 Stream 中元素的数量,用于统计流中元素个数 。
toArray() 将 Stream 中的元素收集起来,存储到一个数组中返回 。
collect(Collector collector) 根据传入的Collector,将 Stream 中的元素收集到对应的集合(如ListSet等)中 。

解释: 

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;

public class StreamDemo10 {
    public static void main(String[] args) {
        ArrayList list2 = new ArrayList<>();
        Collections.addAll(list2,"燕知春-女-20","秦叮咚-女-21","楚天秋-男-24","齐夏-男-19");

//        收集List集合当中
//        需求:
//        我要把所有男性收集起来


//        Consumer的泛型:表示流中数据的类型
//        accept方法的形参s:表示流中的每个数据
//        方法体:对每一个数据的处理操作
//        list2.stream().forEach(new Consumer() {
//            @Override
//            public void accept(String s) {
//                System.out.println(s);
//            }
//        });

        list2.stream().forEach(s->System.out.println(s));

//        long count();统计数量
        long count = list2.stream().count();
        System.out.println(count);

        System.out.println();
//        toArray()     收集流中的数据,放到数组中
//        Object[] arr=list2.stream().toArray();
//        System.out.println(Arrays.toString(arr));

//        如果要放在指定的String类型中
//        <>里面要放转换成的数据类型
//        apply的形参:流中数据的个数,要跟数组的长度保持一致
//        apply的返回值:具体类型的数组
//        方法体:就是创建数组

//        toArray方法的参数的作用:负责创建一个指定类型的数组
//        toarray方法的底层:依次得到流中的每个数据
//        toArray方法的返回值:一个装着流中所有的数据的数组
        String[] array = list2.stream().toArray(new IntFunction() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.println(Arrays.toString(array));

//        修改Lambda
    String[] arr2=list2.stream().toArray(value0->new String[value0]);
    System.out.println(Arrays.toString(arr2));

    }
}

收集方法Collect

可以把数据收集起来装到Collect里面的集合中

package com.itheima.demo1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class StreamDemo11 {
    public static void main(String[] args) {
        ArrayList list2 = new ArrayList<>();
        Collections.addAll(list2,"燕知春-女-20","秦叮咚-女-21","楚天秋-男-24","齐夏-男-19");
//收集起来装进list集合中
        List collect = list2.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList());
        System.out.println(collect);

//        收集在map集合:
//        注意点:如果要收集多个数据到map集合中键不能重复
        Map collect1 = list2.stream()
                .filter(s -> "男".equals(s.split("-")[1]))
                /***
                 * toMap :
                 * 参数一表示键的生成规则
                 * 参数二表示值的生成规则
                 * 参数一:
                 * Function
                 * 泛型一:表示流中每一个数据的类型
                 * 泛型二:表示 Map 集合中键的数据类型
                 * 方法:apply
                 * 形参:依次表示流里面的每一个数据
                 * 方法体:生成键的代码
                 * 返回值:已经生成的键
                 * 参数二:
                 * Function
                 * 泛型一:表示流中每一个数据的类型
                 * 泛型二:表示 Map 集合中值的数据类型
                 * 方法:apply
                 * 形参:依次表示流里面的每一个数据
                 * 方法体:生成值的代码
                 * 返回值:已经生成的值
                 */
                .collect(Collectors.toMap(new Function() {
                    @Override
                    //第一个Strting表示返回的数据,第二个表示流里面的数据(要转到map集合中)
                    public String apply(String s) {

                        return s.split("-")[0];
                    }
                }, new Function() {
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s.split("-")[2]);
                    }
                }));


                System.out.println(collect1);

                list2.stream()
                        .filter(s->"男".equals(s.split("-")[1]))
                        .collect(Collectors.toMap(s->s.split("-")[0],s-> Integer.parseInt(s.split("-")[2])));
    }
}

 总结:

  1. Stream 流的作用
    结合了 Lambda 表达式,简化集合、数组的操作
  2. Stream 的使用步骤
    ● 获取 Stream 流对象
    ● 使用中间方法处理数据
    ● 使用终结方法处理数据
  3. 如何获取 Stream 流对象
    ● 单列集合:Collection 中的默认方法 stream
    ● 双列集合:不能直接获取
    ● 数组:Arrays 工具类型中的静态方法 stream
    ● 一堆零散的数据:Stream 接口中的静态方法 of
  4. 常见方法
    中间方法: filter,limit,skip,distinct,concat,map
    终结方法: forEach,count,collect

你可能感兴趣的:(Java学习,java,算法,开发语言)