Java Stream流

文章目录

1. Java Stream流

1.1 Stream流简介

1. Stream 流介绍

  • Stream 流是 Java8 提供给开发者的一组 操作集合 的 API。
  • 它将要处理的元素看作是一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选、排序、聚合等。

2. Stream 流的好处

假设有以下字符串 "1","2","123","234","12345",我们想要获得长度大于4的字符串。以下提供两种写法.

  1. 未使用 stream流
import java.util.ArrayList;

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

        // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        // 创建新集合,用来存储过滤后的字符串元素
        ArrayList<String> newList = new ArrayList<String>();

        list.add("1");
        list.add("2");
        list.add("123");
        list.add("234");
        list.add("12345");

        // 把长度大于4的字符串存储
        for(String s:list) {
            if(s.length()>4)
                newList.add(s);
        }

        // 输出 newList
        for(String s:newList){
            System.out.println(s);
        }

    }
}
  1. 使用 stream 流
import java.util.ArrayList;

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

        // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("1");
        list.add("2");
        list.add("123");
        list.add("234");
        list.add("12345");

        // Stream 流写法
        list.stream().filter(s -> s.length() > 4).forEach(System.out::println);

    }
}

好处
1. 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义
2. Stream流把真正的函数式编程风格引入到Java中
3. 可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码
4. 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象

1.2 Stream流的常见生成方式

1. Stream流的思想

Java Stream流

2. 生成Stream流的方式

  • Collection体系集合
    使用默认方法stream()生成流, default Stream stream()
  • Map体系集合
    把Map转成Set集合,间接的生成流
  • 数组
    通过Stream接口的静态方法of(T… values)生成流

3. 代码演示

import java.util.*;
import java.util.stream.Stream;

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

        //Collection体系的集合可以使用默认方法stream()生成流
        List<String> list = new ArrayList<String>();
        Stream<String> listStream = list.stream();
        
        Set<String> set = new HashSet<String>();
        Stream<String> setStream = set.stream();

        //Map体系的集合间接的生成流
        Map<String,Integer> map = new HashMap<String, Integer>();
        Stream<String> keyStream = map.keySet().stream();
        Stream<Integer> valueStream = map.values().stream();
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
        
        //数组可以通过Stream接口的静态方法of(T... values)生成流
        String[] strArray = {"hello","world","java"};
        Stream<String> strArrayStream = Stream.of(strArray);
        Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
        Stream<Integer> intStream = Stream.of(10, 20, 30);
    }
}

1.3 Stream流中间操作方法

1. 概念

  • 中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。

2. 常见方法

方法名 说明
Stream filter(Predicate predicate) 用于对流中的数据进行过滤
Stream limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据
Stream skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流
static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流
Stream distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流
Stream sorted() 返回由此流的元素组成的流,根据自然顺序排序
Stream sorted(Comparator comparator) 返回由该流的元素组成的流,根据提供的Comparator进行排序
Stream map(Function mapper) 返回由给定函数应用于此流的元素的结果组成的流
IntStream mapToInt(ToIntFunction mapper) 返回一个IntStream其中包含将给定函数应用于此流的元素的结果

3. filter代码演示

import java.util.ArrayList;

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

        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();
        list.add("黄晓明");
        list.add("张三");
        list.add("张无忌");
        list.add("李子明");
        list.add("樊星辰");
        list.add("李双双");

        // 把list集合中以张开头的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
        System.out.println("--------");

        // 把list集合中长度为3的元素在控制台输出
        list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
        System.out.println("--------");

        // 把list集合中以张开头的,长度为3的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() ==
                3).forEach(System.out::println);
    }
}

4. limit&skip代码演示

import java.util.ArrayList;

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

        // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();
        list.add("黄晓明");
        list.add("张三");
        list.add("张无忌");
        list.add("李子明");
        list.add("樊星辰");
        list.add("李双双");

        // 取前3个数据在控制台输出
        list.stream().limit(3).forEach(System.out::println);
        System.out.println("--------");

        // 跳过3个元素,把剩下的元素在控制台输出
        list.stream().skip(3).forEach(System.out::println);
        System.out.println("--------");

        // 跳过2个元素,把剩下的元素中前2个在控制台输出
        list.stream().skip(2).limit(2).forEach(System.out::println);
    }
}

5. concat&distinct代码演示

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

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

        // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();
        
        list.add("黄晓明");
        list.add("张三");
        list.add("张无忌");
        list.add("李子明");
        list.add("樊星辰");
        list.add("李双双");

        // 取前4个数据组成一个流
        Stream<String> s1 = list.stream().limit(4);

        // 跳过2个数据组成一个流
        Stream<String> s2 = list.stream().skip(2);
        
        // 合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
        Stream.concat(s1,s2).distinct().forEach(System.out::println);
    }
}

6. sorted代码演示

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

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

        // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("huangxiaoming");
        list.add("zhangsan");
        list.add("zhangwuji");
        list.add("liziming");
        list.add("fanxingchen");
        list.add("lishuangshuang");

        // 按照字母顺序把数据在控制台输出
        list.stream().sorted().forEach(System.out::println);

        //按照字符串长度把数据在控制台输出
        list.stream().sorted((s1,s2) -> {
            int num = s1.length()-s2.length();
            int num2 = num==0?s1.compareTo(s2):num;
            return num2;
        }).forEach(System.out::println);
        
    }
}

7. map&mapToInt代码演示

import java.util.ArrayList;

public class Demo {
    public static void main(String[] args) {
        
        //创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();
        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");
    
        // 将集合中的字符串数据转换为整数之后在控制台输出
        // list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
        // list.stream().map(Integer::parseInt).forEach(System.out::println);
        // list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
        
        //int sum() 返回此流中元素的总和
        int result = list.stream().mapToInt(Integer::parseInt).sum();
        System.out.println(result);
    }
}

1.4 Stream流终结操作方法

1. 概念

终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。

2. 常见方法

方法名 说明
void forEach(Consumer action) 对此流的每个元素执行操作
long count() 返回此流中的元素数

3. 代码演示

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

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

        // 创建一个集合,存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("黄晓明");
        list.add("张三");
        list.add("张无忌");
        list.add("李子明");
        list.add("樊星辰");
        list.add("李双双");

        // 把集合中的元素在控制台输出
        // list.stream().forEach(System.out::println);
       
        // 统计集合中有几个以张开头的元素,并把统计结果在控制台输出
        long count = list.stream().filter(s -> s.startsWith("张")).count();
        System.out.println(count);
    }
}

1.5 Stream流的收集操作

1. 概念

对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中。

2. 常用方法

方法名 说明
R collect(Collector collector) 把结果收集到集合中

3. 工具类Collectors提供了具体的收集方式

方法名 说明
public static Collector toList() 把元素收集到List集合中
public static Collector toSet() 把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中

4. 代码演示

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

        //创建List集合对象
        List<String> list = new ArrayList<String>();
        list.add("小红");
        list.add("小明");
        list.add("小王");
        list.add("小蓝");

        // 得到名字为3个字的流
        Stream<String> listStream = list.stream().filter(s -> s.length() == 3);

        // 把使用Stream流操作完毕的数据收集到List集合中并遍历
        List<String> names = listStream.collect(Collectors.toList());

        for(String name : names) {
            System.out.println(name);
        }


        //创建Set集合对象
        Set<Integer> set = new HashSet<Integer>();
        set.add(10);
        set.add(20);
        set.add(37);
        set.add(31);
        set.add(35);

        // 得到年龄大于25的流
        Stream<Integer> setStream = set.stream().filter(age -> age > 25);

        // 把使用Stream流操作完毕的数据收集到Set集合中并遍历
        Set<Integer> ages = setStream.collect(Collectors.toSet());

        for(Integer age : ages) {
            System.out.println(age);
        }


        //定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
        String[] strArray = {"小红,20", "小明,29", "小王王,33", "小白,25"};

        // 得到字符串中年龄数据大于28的流
        Stream<String> arrayStream = Stream.of(strArray).filter(s ->
                Integer.parseInt(s.split(",")[1]) > 28);

        // 把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
        Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s ->
                s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));

        Set<String> keySet = map.keySet();

        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + "," + value);
        }
    }
}
上一篇:Kotlin学习第一章(二)


下一篇:都2202年了,再不学ES6你就out了