java-----Stream流

什么是Stream?

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等

Stream流的作用:

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

Stream流的使用步骤:

        ①先得到一条Stream流(流水线),并把数据放上去

        ②利用Stream流中的API进行各种操作:比如

中间方法:(过滤、转换) 方法调用完毕之后,还可以调用其他方法

终结方法:(统计、打印) 最后一步,调用完毕之后,不能调用其它方法

总的来说三步:

        1.先得到一条Stream流(流水线),并把数据放上去

        2.使用中间方法对流水线上的数据进行操作

        3.使用终结方法对流水线上的数据进行操作

让我们来一步步介绍

①得到一条Stream流(流水线),并把数据放上去

获取方式方法名说明
单列集合default Stream<E>stream()Collection中的默认方法
双列集合无法直接使用Stream流
数组public static<T>Stream<T>stream(T[]array)Arrays工具类中的静态方法
一堆零散数据public static<T>Stream<T>of(T...values)Stream接口中的静态方法

方法演示:       

package StreamDemo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class demo1 {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"a","b","c","d","e");
        Stream<String> stream = list.stream();//ctrl+v自动生成左边

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

        //双列集合获取Stream流时必须利用keySet()或者entrySet()方法获取单列集合,然后再获取流
        HashMap<String,Integer> hm=new HashMap<>();
        hm.put("aaa",111);
        hm.put("bbb",222);

        hm.keySet().stream().forEach(s->System.out.println(s));
        hm.entrySet().stream().forEach(s->System.out.println(s.getKey()));

        int []arr={1,2,3,4,5,6};
        Arrays.stream(arr).forEach(s->System.out.println(s));
        
        //Stream接口中静态方法of的细节
        //方法形参是一个可变参数,可以传递一堆零散数据,也可以传递数组
        //但是数组必须是引用数据类型,如果传递基本数据类型,会把整个数组当作一个元素,放入Stream中
        Stream.of(arr).forEach(s->System.out.println(s));

        String []arr2={"a","b","c"};
        Stream.of(arr2).forEach(s->System.out.println(s));
    }
}



运行结果:
aaa
bbb
aaa
bbb
1
2
3
4
5
6
[I@7699a589
a
b
c

②使用中间方法对流水线上的数据进行操作

名称说明
Stream<T>filter(Predicate<?super T>) predicate过滤
Stream<T>limit(long maxSize)获取前几个元素
Stream<T>skip(long n)跳过前几个元素
Stream<T>distinct元素去重
static<T>Stream<T>concat(Stream a,Stream b)合并a和b为一个流
static<R>map(Function<T,R> mapper)转换流中的数据类型

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

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

代码演示:

package StreamDemo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;

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

        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠三","张良","王二麻子","谢广坤");

        //1.filter 过滤,把张开头的留下,其余过滤不变
        System.out.print("filter:把张开头的留下");
        Stream<String> stream = list.stream();
        stream.filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                //如果为true,则把当前数据的留下
                //如果为false,则把当前数据舍弃
                return s.startsWith("张");
            }
        }).forEach(s->System.out.print(s+" "));
        System.out.println();
        //把姓张且长度为3进行过滤
        //以下的方法会报错 stream has already been operated upon or closed :正好验证了注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
        //stream.filter(s->s.length()==3).forEach(s->System.out.println(s));
        //那么我们试试链式编程
        System.out.print("filter链式编程:");
        list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s->System.out.print(s+" "));
        System.out.println();
        System.out.print("集合里面的数据:");
        System.out.println(list);//注意2:修改Stream流中数据,不会影响原来的集合或者数组中的数据

        //limit 获取前三个元素
        System.out.print("limit 获取前三个元素");
        list.stream().limit(3).forEach(s->System.out.print(s+" "));
        System.out.println();
        System.out.print("skip 跳过前几个元素:");
        list.stream().skip(3).forEach(s->System.out.print(s+" "));
        System.out.println();
        System.out.print("去重之后:");
        ArrayList<String> list2=new ArrayList();
        Collections.addAll(list2,"张无忌","张无忌","张无忌","张无忌","张无忌","张无忌","张无忌","王二麻子","谢广坤");
        //distinct 去重 看源码可以知道distinct底层时hashSet
        list2.stream().distinct().forEach(s->System.out.print(s+" "));

        //concat 合并两个流
        System.out.println("concat 合并两个流:");
        Stream.concat(list.stream(),list2.stream()).forEach(s->System.out.print(s+" "));
        System.out.println();

        //map转换流中的数据类型
        System.out.print("stream.map转换数据类型 获取集合中的年龄:");
        ArrayList<String> list3=new ArrayList<>();
        Collections.addAll(list3,"张无忌-13","周芷若-14","赵敏-15","张强-16","张三丰-15");
        list3.stream().map(new Function<String, Integer>() {//函数式接口
            @Override
            public Integer apply(String s) {
                String []arr=s.split("-");
                int x=Integer.parseInt(arr[1]);
                return x;
            }
        }).forEach(s->System.out.print(s+" "));
        System.out.println();
    }
}

 运行结果:

filter:把张开头的留下张无忌 张强 张三丰 张翠三 张良 
filter链式编程:张无忌 张三丰 张翠三 
集合里面的数据:[张无忌, 周芷若, 赵敏, 张强, 张三丰, 张翠三, 张良, 王二麻子, 谢广坤]
limit 获取前三个元素张无忌 周芷若 赵敏 
skip 跳过前几个元素:张强 张三丰 张翠三 张良 王二麻子 谢广坤 
去重之后:张无忌 王二麻子 谢广坤 concat 合并两个流:
张无忌 周芷若 赵敏 张强 张三丰 张翠三 张良 王二麻子 谢广坤 张无忌 张无忌 张无忌 张无忌 张无忌 张无忌 张无忌 王二麻子 谢广坤 
stream.map转换数据类型 获取集合中的年龄:
13 14 15 16 15 
 

 ③Stream流中的终结方法

名称        说明
void forEach(Consumer action)遍历
long count()统计
toArray()收集流中的数据,放到数组中
collect(Collector collector)收集流中的数据,放到集合中

package StreamDemo;

import java.util.*;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class demo4 {
    public static void main(String[] args) {
        System.out.println("forEach获取流中的每一个数据");
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠三","张良","王二麻子","谢广坤");

        list.stream().forEach(s->System.out.print(s+" "));
        System.out.println();
        System.out.println("count统计流中的数据个数:");
        System.out.print(list.stream().count());
        System.out.println();

        System.out.println("收集流中的数据,放到数组里");

        //apply的形参:流中数据的个数
        String []arr=list.stream().toArray(new IntFunction<String[]>() {
            @Override
            public String[] apply(int value) {
                return new String[value];
            }
        });
        System.out.print(Arrays.toString(arr));
        System.out.println();

        ArrayList<String> list3=new ArrayList<>();
        Collections.addAll(list3,"张无忌-13-男","周芷若-14-女","赵敏-15-女","张强-16-男","张三丰-15-男","张三丰-15-男");

        System.out.println("collect方法收集流中的数据并把其放入集合中");
        //获取到所有的男性,并把其放到集合中
        List<String> list4=list3.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.split("-")[2].equals("男");
            }
        }).collect(Collectors.toList());
        System.out.println("收集到list集合中:"+list4);

        //放入Set集合

        Set<String> set=list3.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.split("-")[2].equals("男");
            }
        }).collect(Collectors.toSet());
        System.out.println("收集到set集合中:"+set);

        //收集到map集合中 键姓名 值男性
        /*
         toMap:
            参数一表示键的生成规则
            参数二表示值的生成规则
            参数一:
                Function泛型一:表示流中每一个数据的类型
                        泛型二:表示map集合中键的数据类型
                方法apply形参:依次表示流里面的每一个数据
                            方法体:生成键的代码
                            返回值:已经生成的键
             参数二:
                Function泛型一:表示流中每一个数据的类型
                        泛型二:表示map集合中值的数据类型
                方法apply形参:依次表示流里面的每一个数据
                            方法体:生成值的代码
                            返回值:已经生成的值
      */
        ArrayList<String> list5=new ArrayList<>();
        Collections.addAll(list5,"张无忌-13-男","周芷若-14-女","赵敏-15-女","张强-16-男","张三丰-15-男");
        //注意点
        //键不能重复,不然会报错
        Map<String,String> map=list5.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.split("-")[2].equals("男");
            }
        }).collect(Collectors.toMap(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.split("-")[0];
            }
        }, new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.split("-")[2];
            }
        }));//写键的规则和值的规则
        System.out.println("收集到,map集合中:"+map);
    }



}

 运行结果:

forEach获取流中的每一个数据
张无忌 周芷若 赵敏 张强 张三丰 张翠三 张良 王二麻子 谢广坤 
count统计流中的数据个数:
9
收集流中的数据,放到数组里
[张无忌, 周芷若, 赵敏, 张强, 张三丰, 张翠三, 张良, 王二麻子, 谢广坤]
collect方法收集流中的数据并把其放入集合中
收集到list集合中:[张无忌-13-男, 张强-16-男, 张三丰-15-男, 张三丰-15-男]
收集到set集合中:[张强-16-男, 张三丰-15-男, 张无忌-13-男]
收集到,map集合中:{张强=男, 张三丰=男, 张无忌=男}

内容来自Stream流-02-Stream流的思想和获取Stream流_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值