Java集合Stream流操作的基本使用教程分享

目录
  • 事前准备
  • Filter
  • Sorted
  • Map
  • Match
  • Count
  • Reduce
  • 总结

Java 中可以使用 java.util.Stream 对一个集合(实现了java.util.Collection接口的类)做各种操作,例如:求和、过滤、排序等等。

这些操作可能是中间操作——返回一个 Stream 流,或者是终端操作——返回一个结果。

流操作并不会影响原来的集合,可以简单认为,流操作是把集合中的一个元素逐个复制放到一个首尾相接的流动的水槽中。

Stream 流支持同步执行,也支持并发执行。如果我们直接获取 stream 流,得到的是同步执行的 stream 流;如果调用方法 parallelStream,则得到一个可以并发执行的 Stream 流。

注意:Map不支持 Stream 流,但是它的 KeyValue 支持,因为它们实现了 Set 接口。

事前准备

演示 Stream 流的提前准备,创建几个类以供测试

  • 新建一个工具类,方便创建集合。
  • 新建两个类,例如开发中常见的数据库实体类和 DTO 类。
 public class MyUtil {
 ​
     private static List<String> list = new ArrayList<>();
     private static List<Student> students = new ArrayList<>();
 ​
     static {
         list.add("abc");
         list.add("xyz");
         list.add("fgh");
         list.add("abc");
         list.add("def");
         list.add("xyz");
         list.add("efg");
 ​
         Student s1 = new Student();
         s1.setAge("16");
         s1.setId(UUID.randomUUID().toString());
         s1.setName("张三");
         s1.setMajor("计算机科学与技术");
         Student s2 = new Student();
         s2.setAge("18");
         s2.setId(UUID.randomUUID().toString());
         s2.setName("李四");
         s2.setMajor("物联网工程");
         Student s3 = new Student();
         s3.setAge("20");
         s3.setId(UUID.randomUUID().toString());
         s3.setName("王五");
         s3.setMajor("网络工程");
         students.add(s1);
         students.add(s2);
         students.add(s3);
     }
 ​
     public static List<String> getList() {
         return list;
     }
     public static List<Student> getStudents() {
         return students;
     }
 }
 ​
 public class Student {
 ​
     private String id;
     private String name;
     private String age;
     private String major;

 }
 ​
 public class StudentDTO {
 ​
     private String name;
     private String major;
 }

Filter

filter 可以帮助我们过滤流中的某些元素,其方法签名如下

 /*
 过滤操作,
 Predicate 相当于一个谓词,即断言流中的元素满足某个条件,返回一个 布尔值
 */
 Stream<T> filter(Predicate<? super T> predicate);

具体使用方法如下:

 public class Main {
 ​
     public static void main(String[] args) {
         List<String> list = MyUtil.getList();
         System.out.println("过滤操作之前:");
         System.out.println(list);
         // 过滤不以 a 开头的字符串,collect() 将流中的元素放到一个新的集合中
         List<String> newList = list.stream().filter(s -> !s.startsWith("a")).collect(Collectors.toList());
         System.out.println("-------------------------");
         System.out.println("过滤操作之后:");
         System.out.println(newList);
     }
 }
 ​
 ======== 输出 =========
 过滤操作之前:
 [abc, xyz, fgh, abc, def, xyz, efg]
 -------------------------
 过滤操作之后:
 [xyz, fgh, def, xyz, efg]

Sorted

sorted 可以帮助我们排序流中的元素,方法签名如下:

 /*
 中间操作,传入一个 Comparator,对流中的元素进行排序,如果不传入,则使用默认的 Comparable 排序
 对原集合不影响
 */
 Stream<T> sorted(Comparator<? super T> comparator);

具体使用方法如下:

 public class Main {
 ​
     public static void main(String[] args) {
         List<String> list = MyUtil.getList();
         System.out.println("排序操作之前:");
         System.out.println(list);
         List<String> newList = list.stream().sorted().collect(Collectors.toList());
         System.out.println("-------------------------");
         System.out.println("排序操作之后:");
         System.out.println(newList);
         System.out.println("自定义排序:");
         // 倒序排序。 forEach 方法可以用传入的方法 逐个 处理流中的元素
         list.stream().sorted((s1, s2)-> -s1.compareTo(s2)).forEach(System.out::println);
     }
 }
 ​
 ======== 输出 =========
 排序操作之前:
 [abc, xyz, fgh, abc, def, xyz, efg]
 -------------------------
 排序操作之后:
 [abc, abc, def, efg, fgh, xyz, xyz]
 自定义排序:
 xyz
 xyz
 fgh
 efg
 def
 abc
 abc

Map

Map 操作可以帮助我们将流中的一类元素映射为另一类元素,最典型的应用就是可以用来将数据库实体类转换为供前端使用的 DTO 类。方法签名如下:

 /*
 中间操作,可以将一个对象转化为另一个对象
 例如做 DTO 数据转换
 */
 <R> Stream<R> map(Function<? super T, ? extends R> mapper);

具体使用方法如下:

 public class Main {
 ​
     public static void main(String[] args) {
         List<Student> students = MyUtil.getStudents();
         System.out.println("map 操作之前");
         System.out.println(students);
         // collect 方法可以将流中的元素收集到一个 Collection 中,如果有去除重复元素的需求,可以考虑收集到 Set 中
         List<StudentDTO> dtos = students.stream().map(student -> {
             StudentDTO dto = new StudentDTO();
             dto.setName(student.getName());
             dto.setMajor(student.getMajor());
             return dto;
         }).collect(Collectors.toList());
         System.out.println("-------------------------");
         System.out.println("map 操作之后");
         System.out.println(dtos);
     }
 }
 ​
 ======== 输出 =========
 map 操作之前
 [Student{id='cb5726cd-e73a-443e-95e5-155aa6e876ae', name='张三', age='16', major='计算机科学与技术'}, Student{id='94478bae-b2ee-4c43-bac0-12f45f4099cd', name='李四', age='18', major='物联网工程'}, Student{id='5fdd9e19-f7cf-4c61-b506-0ef58a36dcbe', name='王五', age='20', major='网络工程'}]
 -------------------------
 map 操作之后
 [StudentDTO{name='张三', major='计算机科学与技术'}, StudentDTO{name='李四', major='物联网工程'}, StudentDTO{name='王五', major='网络工程'}]

Match

 /*
 终端操作,可以用来匹配操作,返回一个 boolean 值
 可以方便地匹配集合中是否存在某种元素
 */
 // 只要集合中有一个匹配,就返回 true
 boolean anyMatch(Predicate<? super T> predicate);
 // 集合中所有元素都匹配,才返回 true
 boolean allMatch(Predicate<? super T> predicate);
 // 集合中所有元素都不匹配,返回 true
 boolean noneMatch(Predicate<? super T> predicate);

具体使用方法如下:

 public class Main {
 ​
     public static void main(String[] args) {
         List<String> list = MyUtil.getList();
         System.out.println("集合中的所有元素是否都以 a 开头");
         System.out.println(list.stream().allMatch(s -> s.startsWith("a")));
 ​
         System.out.println("集合中是否存在元素以 a 开头");
         System.out.println(list.stream().anyMatch(s -> s.startsWith("a")));
 ​
         System.out.println("集合中的元素是否都不以 a 开头(相当于 allMatch 的取反):");
         System.out.println(list.stream().noneMatch(s -> s.startsWith("a")));
     }
 }
 ​
 ======== 输出 =========
 集合中的所有元素是否都以 a 开头
 false
 集合中是否存在元素以 a 开头
 true
 集合中的元素是否都不以 a 开头(相当于 allMatch 的取反):
 false

Count

 /*
 终端操作,返回 stream 流中及集合中的元素个数,返回一个 long 类型
 */
 long count();

具体使用方法如下:

 public class Main {
 ​
     public static void main(String[] args) {
         List<String> list = MyUtil.getList();
         System.out.println(list);
         System.out.println("集合中的个数:" + list.size());
 ​
         long count = list.stream().filter(s -> s.startsWith("a")).count();
         System.out.println("集合中以 a 开头的元素个数:" + count);
     }
 }
 ​
 ======== 输出 =========
 [abc, xyz, fgh, abc, def, xyz, efg]
 集合中的个数:7
 集合中以 a 开头的元素个数:2

Reduce

 /*
 终端操作,可以理解为减少集合的个数,对集合中的元素不断进行累加,最终只得到一个元素
 Optional 包含一个对象,可以防止空指针异常
 */
 Optional<T> reduce(BinaryOperator<T> accumulator);

具体使用方法如下:

 public class Main {
 ​
     public static void main(String[] args) {
         List<String> list = MyUtil.getList();
         // 可以理解为减少集合的个数,对集合中的元素不断进行累加,最终只得到一个元素
         // 例如对数字集合进行累加进行求和
         String s = list.stream().reduce((s1, s2) -> s1 + "###" + s2).get();
         System.out.println(s);
     }
 }
 ​
 ======== 输出 =========
 abc###xyz###fgh###abc###def###xyz###efg

总结

可以看到,stream 流操作并没有什么使用难度,但如果不熟悉 Lambda 表达式开发和函数引用,则使用起来可能会稍微吃力些。

置于并发流的使用,只需要使用集合的方法parallelStream(),就可以获得一个并发流,在编写代码上基本和同步流没什么区别,因此学会上面的基本用法基本足够了,实际使用过程中,根据实际情况决定如何使用即可。

以上就是Java集合Stream流操作的基本使用教程分享的详细内容,更多关于Java Stream流操作的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java8 Stream流的常用方法汇总

    目录 1.快速创建List (1).new一个list,一个一个添加 (2).Stream流:创建动态list,可以添加元素 (3).如果创建一个固定长度的list,可以使用Arrays.asList(…args)直接返回一个list 2.取对象的某一列: (1).遍历 (2).Stream流:map 3.过滤,或者说是根据一个判断条件筛选出目标对象 (1).遍历加 if (2).Stream流:filter 4.分组 (1).遍历加 if (2).Stream流:groupingBy 5.求和

  • Java8-Stream流操作List去重问题

    目录 Java8Stream流操作List去重 List列表运用Java8的stream流按某字段去重 问题 思路 Java8Stream流操作List去重 根据属性去重整体去重使用 distinct ArrayList<LabelInfoDTO> collect = labelInfoDTOS.stream(). collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(

  • 一文详解Java中Stream流的使用

    目录 简介 操作1:创建流 操作2:中间操作 筛选(过滤).去重 映射 排序 消费 操作3:终止操作 匹配.最值.个数 收集 规约 简介 说明 本文用实例介绍stream的使用. JDK8新增了Stream(流操作) 处理集合的数据,可执行查找.过滤和映射数据等操作. 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询.可以使用 Stream API 来并行执行操作. 简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式. 特点 不是数据结构

  • Java的Stream流来了解一下

    目录 Stream流 1.什么是Stream流: 2.创建流: 3.Stream的map映射流 4.Stream查找与匹配 总结 Stream流 上篇文章讲了Java 8 的一个新特性:Lambda表达式,在业务中若能熟练的使用,可以节省很多代码量,看着也整洁很多.那么这篇文章将介绍另一个新特性:Stream流,不要看错哈!!!不是打游戏的steam!! 1.什么是Stream流: Stream 是Java 8 提出的一个新概念,不是输入输出的 Stream 流 (和IO流其实没有任何关系哈),

  • Java集合Stream流操作的基本使用教程分享

    目录 事前准备 Filter Sorted Map Match Count Reduce 总结 Java 中可以使用 java.util.Stream 对一个集合(实现了java.util.Collection接口的类)做各种操作,例如:求和.过滤.排序等等. 这些操作可能是中间操作——返回一个 Stream 流,或者是终端操作——返回一个结果. 流操作并不会影响原来的集合,可以简单认为,流操作是把集合中的一个元素逐个复制放到一个首尾相接的流动的水槽中. Stream 流支持同步执行,也支持并发

  • Java 8 Stream流强大的原理

    目录 1.Stream的组成与特点 2.BaseStream接口 3.Stream接口 4.关闭流操作 5.并行流和串行流 6.ParallelStream背后的男人:ForkJoinPool 7.用ForkJoinPool的眼光来看ParallelStream 8.并行流的性能 9.NQ模型 10.遇到顺序 前言: Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象. Stream API可以极大提高Java程序员的生产力,让程

  • Java中Stream流中map和forEach的区别详解

    目录 什么是 stream 流 Map forEach 使用场景 不是很难的知识,但是今天犯错了,记录一下 什么是 stream 流 我们在使用集合或数组对元素进行操作时往往会遇到这种情况:通过对不同类型的存储元素,按照特定条件进行查找.排序.等操作时往往会写一大段代码,而且更要命的是,不同类型的数据,操作的方法也不一样,比如一个存储 Student 实体类和一个只存储 String 类型的集合俩者的操作步骤肯定大不一样且无法通用,而 stream API 就解决了这些问题,对数据操作时进行了统

  • 关于JAVA中stream流的基础处理(获取对象字段和对象批量处理等)

    目录 Stream流程处理情况 1:按指定字段获取集合对象中的字段: 2:按指定字段对集合对象进行排序: 3: 按指定字段对集合对象去重处理 4: 对集合对象批量处理 5: 将集合对象中指定字段转数组 Stream流程处理情况 1:按指定字段获取集合对象中的字段: List<String> idList = initUserList.stream().map(User::getId).collect(Collectors.toList()); 2:按指定字段对集合对象进行排序: List<

  • Java中Stream流去除List重复元素的方法

    本文实例为大家分享了Java中Stream流去除List重复元素的具体代码,供大家参考,具体内容如下 业务场景 在开发中我们常常需要过滤List中的重复对象,而重复的定义往往是根据单个条件或者多个条件,如果是单个条件的话还是比较好处理的,即使不使用工具,代码也可以很容易实现,但如果判断依据不是单个条件,而是多个条件的话,代码实现起来就会比较复杂,此时我们一般就会使用工具来简化开发 单条件去重代码 ArrayList<listData> collect = list.stream().colle

  • python操作oracle的完整教程分享

    1. 连接对象 操作数据库之前,首先要建立数据库连接. 有下面几个方法进行连接. >>>import cx_Oracle >>>db = cx_Oracle.connect('hr', 'hrpwd', 'localhost:1521/XE') >>>db1 = cx_Oracle.connect('hr/hrpwd@localhost:1521/XE') >>>dsn_tns = cx_Oracle.makedsn('localho

  • JDK1.8新特性Stream流式操作的具体使用

    一. 前言 随着Java的发展,越来越多的企业开始使用JDK1.8 版本.JDK1.8 是自 JDK1.5之后最重要的版本,这个版本包含语言.编译器.库.工具.JVM等方面的十多个新特性.本次文章将着重学习Stream. Stream 是JDK1.8 中处理集合的关键抽象概念,Lambda 和 Stream 是JDK1.8新增的函数式编程最有亮点的特性了,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.过滤和映射数据等操作.使用Stream API 对集合数据进行操作,就类似于使用SQ

  • 一篇文章带你了解Java Stream流

    目录 一.Stream流引入 现有一个需求: 1.用常规方法解决需求 2.用Stream流操作集合,获取流,过滤操作,打印输出 二.Stream流的格式 三.获取流 四.Stream流的常用方法 方法演示: 1.count方法: 2.filter方法: 3.forEach方法 4.limit方法 5.map方法 6.skip方法 7.concat方法 五.收集Stream流 总结 一.Stream流引入 Lambda表达式,基于Lambda所带来的函数式编程,又引入了一个全新的Stream概念,

随机推荐