Steam流

发布时间 2023-03-28 23:21:56作者: wdadwa

Stream流概述

Stream流:相当于把要操作的的数据放到流水线上进行各种操作。

Stream流的作用:结合Lambda表达式,简化集合,数组的操作

Stream流一般采用链式编程+Lambda表达式写

使用步骤:

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

  2. 利用Stream流中的API进行各种操作

    过滤,转换,统计,打印等操作

    这些方法可分为:中间方法终结方法

    中间方法:方法调用完毕后,还可调用其他方法。比如过滤

    终结方法:方法调用完毕后,不能调用其他方法了,比如输出打印

Stream流使用

  1. 获取Stream流对象
获取方式 方法名 说明
Collection单列集合 default Stream stream() Collection中的默认方法
Map双列集合 无法直接使用stream流
数组 public static Stream stream(T[] array) Arrays工具类中的静态方法
一堆零散的数据 public static Stream of(T...Values) Stream接口中的静态方法,T...Value是可变参数
import java.util.ArrayList;
import java.util.Collections;
public class Main {
    public static void main(String[] args) {
        //1.Collection单列集合创建Stream流
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"a","b","c","d");
        list.stream().forEach(s-> System.out.println(s));//其中list.stream()就已经获取了stream流对象了
        //.forEach是Stream流中的终结方法
        
        //2.Map集合创建Stream流
        HashMap<String,String> map=new HashMap<>();
        map.put("a","A");
        map.put("b","B");
        map.put("c","C");
        map.keySet().stream()
            .forEach(s-> System.out.println(s+"="+map.get(s)));//这段是Stream流的方法
        map.entrySet().stream()
            .forEach(s-> System.out.println(s.getKey()+"="+s.getValue()));//这段是Stream流的方法
        
        //3.数组获取Stream流
       int[] numbers=new int[]{1,2,3,4,5};
        Arrays.stream(numbers)
            .forEach(n-> System.out.println(n));//这段是Stream流的方法
        
        //4.一堆零散的数据获取Stream流(必须是相同数据类型)
       Stream.of(1,2,3,4,5)
           .forEach(n-> System.out.println(n));//这段是Stream流的方法
        
    }
}
  1. Stream流的中间方法
方法名 说明
Stream filter<Predicate<? super T> 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<T,R> mapper) 转换流中的数据类型

注意:

  1. 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议采用链式编程。
  2. 修改Stream流中的数据,不会影响到原数组或集合中的数据
  3. filter过滤方法中的参数是一个函数式接口,使用Lambda表达式即可
  4. map中的参数也是一个函数式接口,需要使用Lambda表达式简化
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Predicate;
public class Main {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"1","2","3","11","22","33","111","222","333");
        //filter方法详解
        list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length()==1;//s表示流中每一个数据,如果返回值为true表示留下数据,false表示不留下数据
            }
        }).forEach(s-> System.out.println(s));        
		//简化版filter
        list.stream()
            .filter(s->s.length()==1)//过滤,只留下长度为1的数据
            .forEach(s-> System.out.println(s));//遍历输出结过:1,2,3
        
  
        list.stream()
                .limit(4)//获取前4个元素
                .forEach(s-> System.out.println(s)); //遍历结果:1,2,3,11     
        list.stream()
                .skip(4)//跳过前4个元素
                .forEach(s-> System.out.println(s));//遍历结果:"22","33","111","222","333"
        list.add("1");
        list.stream()
                .distinct()//去重
                .forEach(s-> System.out.println(s));//遍历
       
        ArrayList<String> list2=new ArrayList<>();
        Collections.addAll(list,"a","b","c","d","e");
        Stream.concat(list.stream(),list2.stream())//利用Stream流中静态方法发将两个小流合并为一条大流
            .forEach(s-> System.out.println(s));
        
        list.stream()
                .map(s-> Integer.parseInt(s))//将原本的数据类型转化为Int类型
                .forEach(s-> System.out.println(s));        
        //map方法详细写法
        list.stream().map(new Function<String, Integer>() {//第一个泛型是数据原本的类型,第二个泛型是要转化的类型
            @Override
            public Integer apply(String s) {//这个s表示流里面每一个数据
                return Integer.parseInt(s);
            }
        }).forEach(s-> System.out.println(s));  //在这里的forEatch中s就是整数类型了
    }
}
  1. Stream流中的终结方法
方法名 说明
void forEach(Consumer action) 遍历
long count() 统计
toArray(IntFunction<> function) 收集流中数据,放到数组中
collect(Collector collector) 收集流中数据,放到集合中
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 Main {
    public static void main(String[] args) {
        ArrayList<String> list=new ArrayList<>();
        Collections.addAll(list,"1","2","3","11","22","33","111","222","333");
        list.stream().forEach(s-> System.out.println(s));//遍历,这玩意是个函数式接口,方法和集合的forEach是一模一样
        
        long count = list.stream().count();//统计流中数据个数
        System.out.println(count);
        
        //toArray方法详写
        list.stream().toArray(new IntFunction<String[]>() {//IntFunction泛型:具体转化为什么数组
            @Override
            public String[] apply(int value) {//value流中数据的个数
                return new String[value];//方法体:创建数组
            }//返回值:具体的数组
        });        
        //Lambda表达式简化
         list.stream().toArray(value->new String[value]);
        
        //collect方法(可以收集流中数据并放到集合中,可以放到List,Set,Map)
        //1.收集到List集合中(实际创建的是ArrayList)
        List<String> newList = list.stream()//收集到list集合中
                .filter(s -> s.length() == 2)
                .collect(Collectors.toList());//Collectors是Stream接口中的工具类,toList是工具类中的方法
        System.out.println(newList);
        //2.收集到Set中(实际创建的是HashSet)
        Set<String> newSet = list.stream()//注意Set集合特性,无重复元素!!
                .limit(3)
                .collect(Collectors.toSet());
        System.out.println(newSet);           
    }
}

收集到map集合

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.*;
import java.util.stream.Collectors;
public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "1", "2", "3", "11", "22", "33", "111", "222", "333");
        /*
        *这里的toMap(键的生成规则,值生成的规则)
        *在第一个Function里面第一个泛型:流中数据类型,第二个泛型:map集合中键的数据类型
        *apply形参:依次表示流中每个数据
        *方法体:生成键的代码
        *返回值:已经生成的键
        *注意map的键不能重复!
        *
        *在第二个Function里面第一个泛型:流中数据类型,第二个泛型:map集合中值的数据类型
        *apply形参:依次表示流中每个数据
        *方法体:生成键的代码
        *返回值:已经生成值
        */
        Map<String, Integer> map = list.stream()
                .filter(s -> s.length() == 3)
                .collect(Collectors.toMap(new Function<String, String>() {
                    @Override
                    public String apply(String s) {
                        return s.substring(0, 1);
                    }
                }, new Function<String, Integer>() {
                    @Override
                    public Integer apply(String s) {
                        return Integer.parseInt(s.substring(2));
                    }
                }));
        System.out.println(map);
        //简化!
       Map<String, Integer> map = list.stream()
                .filter(s -> s.length() == 3)
                .collect(Collectors.toMap(s-> s.substring(0, 1), s->Integer.parseInt(s.substring(2))));
        
    }
}