Java之Stream流

发布时间 2023-04-09 16:12:53作者: joudys

Stream

学习Stream流需要先了解什么事函数式接口,因为在Stream中的方法参数大都为函数式接口。

函数式接口

有且只有一个抽象方法的接口。函数式接口可以有多个非抽象方法;

Java中内置函数式接口

内置函数式接口:由java官方定义的一些常用的函数式接口。

  1. 消费型接口(Consumer)

    抽象方法 void accept(T t);

    传入一个参数数据,执行相应的业务逻辑。无返回值

  2. 供给型接口(Supplier)

    抽象方法:T get();

    无需参数,按照方法体中的业务逻辑,返回业务执行结果

  3. 函数型接口(Function)

    抽象方法:R apply(T t);

    接受一个参数数据,逻辑处理后,返回一个新的数据值

  4. 断言型接口(Predicate)

    抽象方法:boolean test(T t);

    传入参数后,逻辑判断处理后,返回boolean类型的值

Stream的使用

Stream流创建

方式1:根据Collection获取流,Collection接口中有一个stream方法,可以用来获取流

  •   default Stream<E> stream()
    

方式2:使用Stream接口提供的of方法

  • public static Stream of(T t)

  • static Stream of(T... values)

代码演示:

public class StreamTest {

    final static ArrayList<String> LIST_STREAM = new ArrayList<>();

    static {
        LIST_STREAM.add("张三丰");
        LIST_STREAM.add("张三");
        LIST_STREAM.add("张学友");
        LIST_STREAM.add("张惠美");
        LIST_STREAM.add("张无忌");
        LIST_STREAM.add("白眉鹰王");
        LIST_STREAM.add("紫衫龙王");
        LIST_STREAM.add("金毛狮王");
        LIST_STREAM.add("青翼蝠王");
    }
    //方式1
    @Test
    public void createStreamMethodOneTest(){
        LIST_STREAM.stream()
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 张三丰
         * 张三
         * 张学友
         * 张惠美
         * 张无忌
         * 白眉鹰王
         * 紫衫龙王
         * 金毛狮王
         * 青翼蝠王
         */
    }
    //方式2
     @Test
    public void createStreamMethodTwoTest(){
        Stream.of("张三","王二","赵六")
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 张三
         * 王二
         * 赵六
         */
    }
}

Steam之forEach方法

void forEach(Consumer<? super T> action) 遍历流中的每一个元素,并对元素进行相应的业务处理,无返回值
注意:forEach在Stream中是一个终结方法

@Test
    public void createStreamMethodOneTest(){
        LIST_STREAM.stream()
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 张三丰
         * 张三
         * 张学友
         * 张惠美
         * 张无忌
         * 白眉鹰王
         * 紫衫龙王
         * 金毛狮王
         * 青翼蝠王
         */
    }

Steam之filter方法

Stream filter(Predicate<? super T> predicate)
筛选流中出符合条件的元素,并返回一个新的流

 @Test
    public void  createStreamTest(){
        LIST_STREAM.stream()
                .filter(s -> s.startsWith("张"))
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 张三丰
         * 张三
         * 张学友
         * 张惠美
         * 张无忌
         */
    }

Steam之count方法

long count():统计元素的个数
注意:该方法是终结方法

 @Test
    public void countTest(){
        long count = LIST_STREAM.stream()
                .filter(s -> s.startsWith("张"))
                .count();
        System.out.println(count);
        /**
         * 输出结果:
         * 5
         */
    }

Steam之limit方法

Stream limit(long maxSize)
获取流中的前n个元素,返回一个新的流对象
注意:limit的长度从1开始

collect(Collector<? super T, A, R> collector)
将Stream流对象转成集合对象

 @Test
    public void count(){
        List<String> collect = LIST_STREAM.stream()
                .limit(5)
                .collect(Collectors.toList());
        System.out.println(collect);
        /**
         * 输出结果:
         * [张三丰, 张三, 张学友, 张惠美, 张无忌]
         */
    }

Steam之skip方法

Stream skip(long n)
跳过Stream流对象中的前n个元素,返回一个新的Stream流对象
注意:skip中的参数从1开始,输出时不包含第n个元素

@Test
    public void skipTest(){
        LIST_STREAM.stream()
                .skip(5)
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 白眉鹰王
         * 紫衫龙王
         * 金毛狮王
         * 青翼蝠王
         */
    }

Steam之concat方法

static Stream concat(Stream<? extends T> a, Stream<? extends T> b)
将两个流合并为一个流
注意:该方法为Stream接口中的方法

@Test
    public void concat(){
        Stream<String> stream = Stream.of("张三", "赵四");
        Stream<String> stream1 = Stream.of("王五", "李六");
        Stream.concat(stream, stream1)
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 张三
         * 赵四
         * 王五
         * 李六
         */
    }

Steam之map方法

Stream map(Function<? super T,? extends R> mapper)

对流中的每一个元素进行对应的业务处理,并返回一个新的流

 @Test
    public void mapTest(){
        LIST_STREAM.stream()
                .map(s -> s+"...")
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 张三丰...
         * 张三...
         * 张学友...
         * 张惠美...
         * 张无忌...
         * 白眉鹰王...
         * 紫衫龙王...
         * 金毛狮王...
         * 青翼蝠王...
         */
    }

Steam之flapMap方法

Stream flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
将流中的元素分别进行业务处理后,作为流返回。然后将每个元素流作为流返回

@Test
    public void flatMapTest(){
        LIST_STREAM.stream()
                .filter(s -> !s.startsWith("张"))
                .flatMap(s -> Stream.of(s).map(s1 -> s1 + "..."))
                .forEach(s -> System.out.println(s));
        /**
         * 输出结果:
         * 白眉鹰王...
         * 紫衫龙王...
         * 金毛狮王...
         * 青翼蝠王...
         */
    }

Stream中map和flapMap的区别

Stream map(Function<? super T,? extends R> mapper)
Stream flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
map中的参数返回的是R,而flap中的参数返回的是Stream<? extends R>
这导致map所操作的流依然是之前流,
但是flapMap却把流中的每一个元素分别变为了流,然后将这些流封装为一个流进行返回。

 @Test
    public void distinctionOfMapAndFlapMapTest(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> list1 = Arrays.asList(6, 7, 8, 9, 10);
        ArrayList<List<Integer>> lists = new ArrayList<>();
        lists.add(list);
        lists.add(list1);

        List<Integer> collect = lists.stream()
                .flatMap(s -> s.stream().map(s1 -> s1 * 2))
                .collect(Collectors.toList());
        System.out.println(collect);

        /**
         * flatmap的作用 —— 把嵌套集合,按照子集合的形式,统一放入到新的一个集合中去,这就叫结果展平!
         * 例如:一个年级的学生,按照班级为单位,如今年段长想统计该年段所有的学生信息,一个flatmap就能轻松搞定,无需再for循环取遍历获取了。
         */
    }