Java流式编程初体验--Stream流基础
2021/7/4 14:21:17
本文主要是介绍Java流式编程初体验--Stream流基础,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Stream流
在JDK8引入了流的概念。本质上是为了对集合的功能进行进一步的完善。使代码更加简洁优雅,还可以并行处理。
什么是流
流,是一系列数据项,它不是一种数据结构。
流可以进行相关的算法和计算,只是它并没有显式地表现,而是在内部进行隐式地操作。
我们可以把流认为就是一条流水线,在流水线上可以进行各种筛选操作。
流的优势
流,解决了两个问题,1.直接实现你”想要什么”,2.可以进行并行处理。
流,的本质,集合Lambda表达式,对传统Java集合的功能强化。
Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。
Stream流的获取
stream流的获取方式只有四种:
- 单列集合 使用collection接口的stream默认方法生成流
- 双列集合 间接获取流 可以先通过keySet或者entrySet方法获取到set集合,在获取stream流
- 数组 Arrays工具类中的静态方法stream生成流
- 同种数据类型的多个数据
1 2 3 4 5
a b c d e
这种形式的数据可以通过 Stream.of(T… values) 用以生成流。
单列集合
private static void method1() { // 单列集合 ArrayList<String> list = new ArrayList<>(); list.add("111"); list.add("222"); list.add("333"); list.add("444"); // 获取流 Stream<String> stream = list.stream(); stream.forEach(str -> System.out.println(str)); }
双列集合(Map)
private static void method2() { // 双列集合(map) HashMap<String, String> map = new HashMap<>(); map.put("1", "a"); map.put("2", "b"); map.put("3", "c"); // 先获取到所有的键key,然后把这个set结合中所有的键放到stream中 map.keySet().stream().forEach(s -> System.out.println(s + "--->" + map.get(s))); System.out.println("============"); // 直接获取所有的键值对对象,然后把这个集合中所有的键值对放到stream流中 map.entrySet().stream().forEach(entry -> System.out.println(entry.getKey() + "--->" + entry.getValue())); }
数组
private static void method3() { // 数组 int[] arr = {1, 2, 3, 4, 5}; Arrays.stream(arr).forEach(a -> System.out.println(a)); }
同种数据类型的多个数据
private static void method4() { // 同种数据类型的多个数据 Stream.of(1, 2, 3, 4, 5).forEach(a -> System.out.println(a)); }
stream流的中间方法
1. filter
- Stream filter(Predicate predicate) 用于对流中的数据进行过滤
Predicate接口中的方法
boolean test(T t) 对给定的参数进行判断,返回一个布尔值
private static void method5() { // 1. Stream filter(Predicate predicate) 用于对流中的数据进行过滤 // * Predicate接口中的方法 // * (1)boolean test(T t) 对给定的参数进行判断,返回一个布尔值 ArrayList<String> arrayList = new ArrayList(); arrayList.add("张三丰"); arrayList.add("张无忌"); arrayList.add("张翠山"); arrayList.add("赵六"); arrayList.add("张亮"); arrayList.add("刘备"); arrayList.add("关于"); // filter方法会获取流中的每个数据 // test方法中的s就是流中的每个数据, // 方法返回值为true,表示这个数据留着, // 为false,着会剔除流中的该数据 // 对数据进行判断,张开头的数据留下, arrayList.stream().filter(new Predicate<String>() { @Override public boolean test(String s) { if (s.startsWith("张")) return true; return false; } }).forEach(str -> System.out.println(str)); System.out.println("------------"); // 接口只有一个抽象方法,所以可以使用lambda表达式替换,简化书写 arrayList.stream().filter(s -> { // if (s.startsWith("张")) return true; // return false; return s.startsWith("张"); }).forEach(str -> System.out.println(str)); }
2. limit
Stream limit(long maxSize) 截取指定参数个数的数据.
打个比方,用户往流中传入了10个数据,我只要前五个,那么就可以使用该方法
private static void method6() { // Stream limit(long maxSize) 截取指定参数个数的数据 ArrayList<String> arrayList = new ArrayList(); arrayList.add("张三丰"); arrayList.add("张无忌"); arrayList.add("张翠山"); arrayList.add("赵六"); arrayList.add("张亮"); arrayList.add("刘备"); arrayList.add("关于"); arrayList.stream().limit(3).forEach(str-> System.out.println(str)); }
3. skip
Stream skip(long n): 跳过指定参数个数的数据
打个比方,用户往流中传入了10个数据,我不要前五个,那个就可以使用该方法,直接跳过前五个数据
private static void method7() { // Stream limit(long maxSize) 截取指定参数个数的数据 ArrayList<String> arrayList = new ArrayList(); arrayList.add("张三丰"); arrayList.add("张无忌"); arrayList.add("张翠山"); arrayList.add("赵六"); arrayList.add("张亮"); arrayList.add("刘备"); arrayList.add("关于"); arrayList.stream().skip(3).forEach(str-> System.out.println(str)); }
4. distinct
Stream distinct() 去除流中重复的元素,依赖hashCode和equals方法(自定义对象需要重写这两个方法)
private static void method8() { // Stream limit(long maxSize) 截取指定参数个数的数据 ArrayList<String> arrayList = new ArrayList(); arrayList.add("张三丰"); arrayList.add("张无忌"); arrayList.add("张翠山"); arrayList.add("张三丰"); arrayList.add("张三丰"); arrayList.add("赵六"); arrayList.add("张亮"); arrayList.add("刘备"); arrayList.add("关于"); arrayList.add("关于"); arrayList.stream().distinct().forEach(str-> System.out.println(str)); }
5. Stream流的静态方法concat
static Stream concat(Stream a,Stream b) 合并a和b两个流
private static void method9() { // Stream limit(long maxSize) 截取指定参数个数的数据 ArrayList<String> arrayList = new ArrayList(); ArrayList<String> arrayList2 = new ArrayList(); arrayList.add("张三丰"); arrayList.add("张无忌"); arrayList.add("张翠山"); arrayList2.add("赵六"); arrayList2.add("张亮"); arrayList2.add("刘备"); arrayList2.add("关于1"); Stream<String> stream = arrayList.stream(); Stream<String> stream2 = arrayList2.stream(); Stream<String> concat = Stream.concat(stream, stream2); concat.forEach(str -> System.out.println(str) ); }
终结方法
一个stream流只能有一个终结方法
是流水线上的最后一个操作
常见的终结方法:
- void forEach(Consumer action)
Consumer接口中的方法 void accept(T t) 对给定的参数执行此操作 - long count() 返回此流中的元素个数
private static void method10() { // Stream limit(long maxSize) 截取指定参数个数的数据 ArrayList<String> arrayList = new ArrayList(); arrayList.add("张三丰"); arrayList.add("张无忌"); arrayList.add("张翠山"); arrayList.add("赵六"); arrayList.add("张亮"); arrayList.add("刘备"); arrayList.stream().forEach(str-> System.out.println(str)); long count = arrayList.stream().count(); System.out.println(count); }
Stream流的收集操作(终结方法)
使用Stream流的方式操作完成后,如何收集流中的数据,留着以后使用?
Stream流的收集方法:
- R collect(Collector collector)
工具类Collectors提供了具体的收集方式
- static Collector toList(): 把元素收集到List集合中
- static Collector toSet(): 把元素收集到set集合中
- static Collector toMap(Function keyMapper,Function valueMapper): 把元素收集到Map集合中
/* * stream流的收集方法 * R collect(Collector collector) * */ ArrayList<Integer> arrayList = new ArrayList(); for (int i = 1; i < 11; i++) { arrayList.add(i); } // 只要偶数 List<Integer> list = arrayList.stream() .filter(number -> number % 2 == 0) // 收集流中的数据,但是不负责创建容器,也不负责把数据添加到容器中 // Collectors.toList() 在底层会创建一个List容器,并把流中的数据添加到List容器中 .collect(Collectors.toList()); System.out.println(list); // Collectors.toSet() 在底层会创建set容器,并把流中的数据加入到容器中 Set<Integer> set = arrayList.stream().filter(number -> number % 2 != 0) .collect(Collectors.toSet()); System.out.println(set);
ArrayList<String> arrayList = new ArrayList<>(); arrayList.add("张三,1"); arrayList.add("李四,2"); arrayList.add("王五,3"); arrayList.stream().filter(str -> { // 获得编号,保留编号小于等于2的 String[] split = str.split(","); return Integer.valueOf(split[1]) <= 2; }).collect(Collectors.toMap( // 第一个表达式,用来获取键,第二个表达式用来获取值 str->str.split(",")[0], str->str.split(",")[1] ));
结论
**注意:**在stream流中是无法直接修改集合或数组等数据源中的数据的。
这篇关于Java流式编程初体验--Stream流基础的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26Mybatis官方生成器资料详解与应用教程
- 2024-11-26Mybatis一级缓存资料详解与实战教程
- 2024-11-26Mybatis一级缓存资料详解:新手快速入门
- 2024-11-26SpringBoot3+JDK17搭建后端资料详尽教程
- 2024-11-26Springboot单体架构搭建资料:新手入门教程
- 2024-11-26Springboot单体架构搭建资料详解与实战教程
- 2024-11-26Springboot框架资料:新手入门教程
- 2024-11-26Springboot企业级开发资料入门教程
- 2024-11-26SpringBoot企业级开发资料详解与实战教程
- 2024-11-26Springboot微服务资料:新手入门全攻略