Java Stream流

Stream流的三类方法

  • 获取Stream

    创建一条流水线,并把数据放到流水线上准备操作

  • 中间方法

    流水线上的操作

    可以执行多个操作

  • 终结方法

    流水线的最后一个操作

    一个Stream流只能有一个终结方法

Stream流的获取方法

Stream流可以使用在 单列集合双列集合数组同种数据类型多个数据 这四种情况下

  • 单列集合

    ArrayList<String> list = new ArrayList<>(List.of("a", "b", "c"));
    list.stream().forEach(s -> System.out.println(s));
    // 输出结果
    // a
    // b
    // c
    
  • 双列集合

    HashMap<String, String> hm = new HashMap<>();
    hm.put("20001", "zhangsan");
    hm.put("20002", "lisi");
    hm.put("20003", "wangwu");
    // 先获取所有的键,然后通过stream流输出键
    hm.keySet().stream().forEach(s -> System.out.println(s));
    // 输出结果
    // 20003
    // 20002
    // 20001
    
    HashMap<String, String> hm = new HashMap<>();
    hm.put("20001", "zhangsan");
    hm.put("20002", "lisi");
    hm.put("20003", "wangwu");
    // 先获取所有的键值对对象,然后通过stream流输出所有对象
    hm.entrySet().stream().forEach(s -> System.out.println(s));
    // 输出结果
    // 20003=wangwu
    // 20002=lisi
    // 20001=zhangsan
    
  • 数组

    int[] arr= {1, 2, 3, 4, 5};
    Arrays.stream(arr).forEach(s -> System.out.println(s));
    // 输出结果
    // 1
    // 2
    // 3
    // 4
    // 5
    
  • 同种数据类型多个数据

    Stream.of(1, 2, 3, 4, 5).forEach(s -> System.out.println(s));
    // 输出结果
    // 1
    // 2
    // 3
    // 4
    // 5
    

Stream流的中间操作常用方法

filter方法

Stream<T> filter(Predicate predicate):用于对流中数据进行过滤

Predicate 接口中只有一个抽象方法 boolean test(T t) 参数 t 为流中的每一个数据,该方法返回一个布尔值,如果返回的结果为 true 则当前数据留下,如果返回的结果为 false 则过滤掉当前数据

  • 实现案例

    • 使用匿名函数作为参数

      ArrayList<String> list = new ArrayList<>(List.of("赵四", "赵围", "张三", "李四"));
      list.stream().filter(new Predicate<String>() {
          @Override
          public boolean test(String s) {
              Boolean result = s.startsWith("赵");
              return result;
          }
      }).forEach(s -> System.out.println(s));
      
      // 输出结果
      // 赵四
      // 赵围
      
    • 使用lambda函数作为参数

      因为Predicate接口中只有一个抽象方法 test,所以可以使用lambda表达式来达到简化代码的目的

      ArrayList<String> list = new ArrayList<>(List.of("赵四", "赵围", "张三", "李四"));
      list.stream().filter((String s) -> {
          Boolean result = s.startsWith("赵");
          return result;
      }).forEach(s -> System.out.println(s));
      
      // 输出结果
      // 赵四
      // 赵围
      
    • 简化lambda函数

      ArrayList<String> list = new ArrayList<>(List.of("赵四", "赵围", "张三", "李四"));
      list.stream().filter(s -> s.startsWith("赵")).forEach(s -> System.out.println(s));
      

limit方法

Stream<T> limit(long maxSize)截取指定参数个数的数据

ArrayList<String> list = new ArrayList<>();
list.add("小明");
list.add("小鸿");
list.add("小红");
list.add("小华");
list.stream().limit(2).forEach(s -> System.out.println(s));

// 输出结果
// 小明
// 小鸿

skip方法

Stream<T> skip(long n)跳过指定参数个数的数据

ArrayList<String> list = new ArrayList<>();
list.add("小明");
list.add("小鸿");
list.add("小红");
list.add("小华");
list.stream().skip(2).forEach(s -> System.out.println(s));

// 输出结果
// 小红
// 小华

concat方法

static <T> Stream<T> concat(Stream a, Stream b)合并 ab 两个流为一个流

ArrayList<String> list = new ArrayList<>();
list.add("小明");
list.add("小鸿");
list.add("小红");
list.add("小华");

ArrayList<String> list2 = new ArrayList<>();
list2.add("小花");
list2.add("小爱");
list2.add("小密");
list2.add("小五");

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

// 输出结果
// 小明
// 小鸿
// 小红
// 小华
// 小花
// 小爱
// 小密
// 小五

distinct方法

Stream<T> distinct():去除流中重复的元素,依赖(hashCode()equals()方法)

ArrayList<String> list = new ArrayList<>();
list.add("小明");
list.add("小鸿");
list.add("小红");
list.add("小华");
list.add("小华");
list.add("小华");
list.stream().distinct().forEach(s -> System.out.println(s));

// 输出结果
小明
小鸿
小红
小华

Stream流的终结操作常用方法

  • forEach(Consumer action):对流的每个元素执行操作
    • Consumer接口中只有一个 void accept(T t) 方法,该方法对给定的参数执行此操作
  • long count():返回流中的元素个数

forEach方法

  • 匿名内部类传参

    ArrayList<String> list = new ArrayList<>(List.of("1", "2", "3"));
    // 匿名内部类传参
    list.stream().forEach(new Consumer<String>() {
        @Override
        public void accept(String s) {
            System.out.println(s);
        }
    });
    
    // 输出结果
    // 1
    // 2
    // 3
    
  • lambda函数传参

    因为Consumer接口里只有一个抽象方法accept,所以可以使用lambda函数简化代替

    ArrayList<String> list = new ArrayList<>(List.of("1", "2", "3"));
    list.stream().forEach((String s) -> {
        System.out.println(s);
    });
    
    // 输出结果
    // 1
    // 2
    // 3
    
  • 简化lambda函数

    ArrayList<String> list = new ArrayList<>(List.of("1", "2", "3"));
    list.stream().forEach(s -> System.out.println(s));
    
    // 输出结果
    // 1
    // 2
    // 3
    

count方法

long count = list.stream().count();
System.out.println(count);

// 输出结果
// 3

Stream流的收集方法

通过stream流获取到的集合、数组等类型的数据进行修改操作,但是源数据是没有改变的,我们无法直接修改源数据,但是我们可以使用相关方法对流中的数据进行保存

  • Stream流的收集方法

    R collect(Collector collector)

  • 工具类Collectors提供的具体收集方式

    • public static <T> Collector toList():把元素收集到 List 集合中

      ArrayList<Integer> list = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 7, 7));
      List<Integer> collectList = list.stream().filter(number -> number % 2 == 1).collect(Collectors.toList());
      System.out.println(collectList); // [1, 3, 5, 7, 7, 7]
      
    • public static <T> Collector toSet():把元素收集到 Set 集合中

      ArrayList<Integer> list = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 7, 7));
      Set<Integer> collectSet = list.stream().filter(number -> number % 2 == 1).collect(Collectors.toSet());
      System.out.println(collectSet); // [1, 3, 5, 7]
      
    • public static <T> Collector toMap(Function keyMapper, Function valueMapper):把元素收集到 Map 集合中

      创建一个 ArrayList 集合,集合添加这些元素 “zhangsan,24”、“lisi,18”、“wangwu,26”、“zhaoliu,20” ,这些元素前面是姓名,后面是年龄;现需将里面的元素筛选出来,条件是年龄大于等于24岁的,并把帅选出来的数据保存到 Map 集合中,姓名为键,年龄为值。

      ArrayList<String> list = new ArrayList<>();
      list.add("zhangsan,24");
      list.add("lisi,18");
      list.add("wangwu,26");
      list.add("zhaoliu,20");
      
      Map<String, String> map = list.stream().filter(s -> {
          String[] split = s.split(",");
          int age = Integer.parseInt(split[1]);
          return age >= 24;
      }).collect(Collectors.toMap(
          s -> s.split(",")[0],
          s -> s.split(",")[1]
      ));
      System.out.println(map); // {zhangsan=24, wangwu=26}
      

      toMap() 里的第一个 lambda 表达式是如何获取 Map 集合元素中的键,第二个 lambda 表达式是如何获取 Map 集合元素中的值

Stream流案例练习

现有两个 ArrayList 集合,分别存储5名男同学和5名女同学的名字,要求完成以下操作:

  • 男同学只要名字为3个字的前三个人
  • 女同学只要姓李的,并且跳过第一个人
  • 将过滤后的男同学和女同学的姓名合并到一起
  • 完成合并操作后得到的元素作为构造方法的参数创建学生对象,然后遍历数据
    • 学生类 Student ,里面有一个成员变量,一个不带参数的构造方法,一个带参数构造方法,以及成员变量对应的 getset 方法,还有 toString() 方法

学生类

package com.cmy.streamdemo;

/**
 * @author chenmingyong
 */
public class Student {
	private String stuName;
	
	public Student(String stuName) {
		this.stuName = stuName;
	}
	
	public String getStuName() {
		return stuName;
	}
	
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	
	@Override
	public String toString() {
		return "Student{" +
				       "stuName='" + stuName + '\'' +
				       '}';
	}
}

测试类

package com.cmy.streamdemo;


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

/**
 * @author chenmingyong
 */
public class Practice {
	public static void main(String[] args) {
		// 创建存储男同学的姓名集合
		ArrayList<String> maleList = new ArrayList<>();
		maleList.add("轩辕浅");
		maleList.add("百里回");
		maleList.add("百殇");
		maleList.add("慕容凰");
		maleList.add("洋希");
		maleList.add("诸葛尘");
		
		// 创建存储女同学的姓名集合
		ArrayList<String> femaleList = new ArrayList<>();
		femaleList.add("李疏寒");
		femaleList.add("凌雪姣");
		femaleList.add("江舞寒");
		femaleList.add("李梦儿");
		femaleList.add("李楠楠");
		femaleList.add("李锦");
		
		// 筛选男同学,只要名字为3个字的前三个人
		Stream<String> maleStream = maleList.stream().filter(male -> male.length() == 3).limit(3);
		// 筛选女同学,只要姓李的,并且跳过第一个人
		Stream<String> femaleStream = femaleList.stream().filter(female -> female.startsWith("李")).skip(1);
		// 合并两个流并将得到的元素作为构造方法的参数创建学生对象,然后遍历数据
		Stream.concat(maleStream, femaleStream).forEach(s -> {
			Student student = new Student(s);
			System.out.println(student);
		});
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员陈_明勇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值