Java 8 API 添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据,类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API 将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如查找,过滤, 排序,聚合等等操作。Stream API可以极大提高Java程序员的工作效率,让代码更简洁,干净。
@Test public void stream(){ //1.1传入可变参数,字符串,数字等 Stream<String> stringStream = Stream.of("Alian", "boy", "cat", "papa"); //1.2传入对象 Stream<User> userStream = Stream.of(new User("BAT031", "胡一菲", "销售部", 28, 3500)); //2.1generate方法参数为Function<T, T>函数型接口的子类,比如产生正奇数 Stream<Integer> oddStream = Stream.iterate(1, (x) -> x + 2); oddStream.limit(5).forEach(System.out::println); //3.1generate方法参数为Supplier<T> 供给型接口,比如生成1-1000的随机数:(int) Math.round(Math.random() * (m - n) + n) Stream<Integer> generateStream = Stream.generate(() -> (int) Math.round(Math.random() * (1000 - 1) + 1)); generateStream.limit(10).forEach(System.out::println);//打印10个随机数 }
stream是顺序流,parallelStream是并行流。
@Test public void streamAndParallelStream(){ //初始化一个list列表 List<String> fruitList = Arrays.asList("apple","banana","orange","watermelon","pear"); //获取一个顺序流 Stream<String> stream = fruitList.stream(); System.out.println("--------获取顺序流的结果-----------"); stream.forEach(System.out::println); //获取一个并行流 Stream<String> parallel = fruitList.parallelStream(); System.out.println("--------获取并行流的结果-----------"); parallel.forEach(System.out::println); }
运行结果:
--------获取顺序流的结果----------- apple banana orange watermelon pear --------获取并行流的结果----------- orange watermelon banana apple pear
@Test public void arraysToStream(){ //初始化一个String数组(当然也可以去其他类型的数组) String[] animal = new String[]{"cat","dog","pig","chicken","duck"}; Stream<String> animalStream = Arrays.stream(animal); animalStream.forEach(System.out::println); }
运行结果:
cat dog pig chicken duck
@Test public void readLineStream() throws FileNotFoundException { //通过BufferedReader获取到一个流(要自己写一个文件哦,比如我这里的"C:\\myStream.txt") BufferedReader bufReader = new BufferedReader(new FileReader("C:\\myStream.txt")); Stream<String> lineStream = bufReader.lines(); lineStream.forEach(System.out::println); }
运行结果:
我在使用Java 8 Stream API进行测试(BufferedReader.lines()方式获取流)
filter方法对原Stream按照指定条件过滤,在新建的Stream中,只包含满足条件的元素,将不满足条件的元素过滤掉。
@Test public void filter() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT001", "胡昊天", "销售部", 28, 3500), new User("BAT002", "王大锤", "销售部", 27, 3000), new User("BAT003", "唐二鹏", "研发部", 32, 9900), new User("BAT004", "王一林", "研发部", 30, 9000)); //过滤出用户表中年龄大于28岁的员工 List<User> collect = userList.stream().filter(f -> f.getAge() > 28).collect(Collectors.toList()); System.out.println("年龄大于28岁的员工信息:" + collect); //过滤出用户表中年龄大于28岁并且工资大于9000元的员工 List<User> collect2 = userList.stream().filter(f -> (f.getAge() > 28 && f.getSalary() > 9000)).collect(Collectors.toList()); System.out.println("年龄大于28岁并且工资大于9000元的员工信息:" + collect2); }
运行结果:
年龄大于28岁的员工信息:[User(id=BAT003, name=唐二鹏, age=32, department=研发部, salary=9900.0), User(id=BAT004, name=王一林, age=30, department=研发部, salary=9000.0)] 年龄大于28岁并且工资大于9000元的员工信息:[User(id=BAT003, name=唐二鹏, age=32, department=研发部, salary=9900.0)]
map接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。map方法将对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。
@Test public void map() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包雅馨", "财务部", 25, 6000), new User("BAT007", "罗考聪", "测试部", 35, 7400.0)); //获取列表中员工的姓名(新生成的Stream只包含转换生成的元素) List<String> collect = userList.stream().map(User::getName).collect(Collectors.toList()); System.out.println("获取到的员工姓名:" + collect); //mapToDouble System.out.println("员工的工资都转成double:"); userList.stream().mapToDouble(User::getSalary).forEach(System.out::println); //mapToInt System.out.println("员工的年龄都转成int:"); userList.stream().mapToInt(User::getAge).forEach(System.out::println); }
运行结果:
获取到的员工姓名:[梁南生, 包雅馨, 罗考聪] 员工的工资都转成double: 8000.0 6000.0 7400.0 员工的年龄都转成int: 27 25 35
flatmap接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流。每个部分流中的每个值成单独小流,再串成一个整体流。即对Stream中的每一个元素通过转换函数转换,不同的是,该换转函数的对象是一个Stream,也不会再创建一个新的Stream,而是将原Stream的元素取代为转换的Stream
@Test public void flatMap() { //flatmap接收的参数是一个Stream System.out.println("一、把流中的短横线替换后输出的结果:"); Stream.of("A-l-i-a-n ","l-o-v-e ","C-S-D-N").flatMap(e->Stream.of(e.split("-"))).forEach(System.out::print); System.out.println(); System.out.println("二、把流中的每个数据乘以10的结果:"); Stream.of(2,5,8,9).flatMap(n->Stream.of(n*10)).forEach(System.out::println); }
运行结果:
一、把流中的短横线替换后输出的结果: Alian love CSDN 二、把流中的每个数据乘以10的结果: 20 50 80 90
peek方法和map一样能得到流中的每一个元素,只不过map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。peek方法会生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数,并且消费函数优先执行。
@Test public void peek() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT008", "张伟杰", "测试部", 24, 7000), new User("BAT009", "胡俊伟", "研发部", 24, 4500)); List<User> collect = userList.stream().peek(p -> p.setDepartment("运维部")).collect(Collectors.toList()); System.out.println("部门都改为运维部:"+collect); }
运行结果:
部门都改为运维部后的信息:[User(id=BAT008, name=张伟杰, age=24, department=运维部, salary=7000.0), User(id=BAT009, name=胡俊伟, age=24, department=运维部, salary=4500.0)]
distinct方法对原Stream中重复的元素进行剔除,生成的新Stream中没有没有重复的元素。
@Test public void distinct() { System.out.println("按照类型去重结果:"); Stream.of(3, 6, 9, 3, 9, 5).distinct().forEach(System.out::println); List<User> userList = Arrays.asList( new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT011", "陶建文", "运维部", 25, 8000)); System.out.println("按照对象去重结果:"); userList.stream().distinct().forEach(System.out::println); }
运行结果:
按照类型去重结果: 3 6 9 5 按照对象去重结果: User(id=BAT010, name=胡健儿, age=23, department=人事部, salary=4000.0) User(id=BAT011, name=陶建文, age=25, department=运维部, salary=8000.0)
sorted方法将对原Stream进行排序,返回一个有序的新Stream。
@Test public void sorted() { //自然排序结果 System.out.println("数字自然排序结果:"); Stream.of(15, 28, 6, 9).sorted().forEach(System.out::println); System.out.println("字符自然排序结果:"); Stream.of("b", "ab", "ba", "c").sorted().forEach(System.out::println); }
运行结果:
数字自然排序结果: 6 9 15 28 字符自然排序结果: ab b ba c
sorted(Comparator)方法接收一个自定义排序规则函数(Comparator)。
@Test public void sortedWithCompare() { List<User> userList = Arrays.asList( new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT011", "陶建文", "运维部", 25, 8000), new User("BAT012", "张萌萌", "行政部", 20, 3500)); //按照年龄升序排序 System.out.println("按照年龄升序排序"); userList.stream().sorted(Comparator.comparingInt(User::getAge)).forEach(System.out::println); //按照年龄倒序排序 System.out.println("按照年龄倒序排序"); userList.stream().sorted(Comparator.comparingInt(User::getAge).reversed()).forEach(System.out::println); }
运行结果:
按照年龄升序排序 User(id=BAT012, name=张萌萌, age=20, department=行政部, salary=3500.0) User(id=BAT010, name=胡健儿, age=23, department=人事部, salary=4000.0) User(id=BAT011, name=陶建文, age=25, department=运维部, salary=8000.0) 按照年龄倒序排序 User(id=BAT011, name=陶建文, age=25, department=运维部, salary=8000.0) User(id=BAT010, name=胡健儿, age=23, department=人事部, salary=4000.0) User(id=BAT012, name=张萌萌, age=20, department=行政部, salary=3500.0)
limit(n)方法限制从流中获得前n个数据。
@Test public void limit() { List<User> userList = Arrays.asList( new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT011", "陶建文", "运维部", 25, 8000), new User("BAT012", "张萌萌", "行政部", 20, 3500)); //按照年龄倒序排序后取前面两条记录 System.out.println("按照年龄倒序排序后取前面两条记录:"); userList.stream().sorted(Comparator.comparingInt(User::getAge).reversed()).limit(2).forEach(System.out::println); }
运行结果:
按照年龄倒序排序后取前面两条记录: User(id=BAT011, name=陶建文, age=25, department=运维部, salary=8000.0) User(id=BAT010, name=胡健儿, age=23, department=人事部, salary=4000.0)
skip(n)方法跳过n元素可以配合limit进行操作。
@Test public void skip() { List<User> userList = Arrays.asList( new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT011", "陶建文", "运维部", 25, 8000), new User("BAT012", "张萌萌", "行政部", 20, 3500)); //按照年龄倒序排序后取前面两条记录 System.out.println("按照年龄倒序排序后跳过一条数据取两条记录:"); userList.stream().sorted(Comparator.comparingInt(User::getAge).reversed()).skip(1).limit(2).forEach(System.out::println); }
运行结果:
按照年龄倒序排序后跳过一条数据取两条记录: User(id=BAT010, name=胡健儿, age=23, department=人事部, salary=4000.0) User(id=BAT012, name=张萌萌, age=20, department=行政部, salary=3500.0)
forEach方法前面已经用了好多次,其用于遍历Stream中的所元素,顺序流下按照插入数据的顺序进行输出,并行流的时候是随机输出的。
@Test public void forEach() { //初始化一个数据列表 List<Integer> list = Arrays.asList(2, 3, 4, 5, 6); System.out.println("顺序流下输出:"); list.stream().sorted().forEach(f -> System.out.println("forEach顺序流下数据:" + f)); System.out.println("并行流下输出:"); list.parallelStream().forEach(f -> System.out.println("forEach并行流下数据:" + f)); List<User> userList = Arrays.asList( new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT011", "陶建文", "运维部", 25, 8000), new User("BAT012", "张萌萌", "行政部", 20, 3500)); //按照年龄倒序排序后取前面两条记录 System.out.println("跳过前面一条数据后输出:"); userList.stream().skip(1).forEach(System.out::println); }
运行结果:
顺序流下输出: forEach顺序流下数据:2 forEach顺序流下数据:3 forEach顺序流下数据:4 forEach顺序流下数据:5 forEach顺序流下数据:6 并行流下输出: forEach并行流下数据:4 forEach并行流下数据:6 forEach并行流下数据:5 forEach并行流下数据:2 forEach并行流下数据:3 跳过前面一条数据后输出: User(id=BAT011, name=陶建文, age=25, department=运维部, salary=8000.0) User(id=BAT012, name=张萌萌, age=20, department=行政部, salary=3500.0)
forEachOrdered方法与forEach类似,都是遍历Stream中的所有元素,不同的是,如果该Stream预先设定了顺序,会按照预先设定的顺序执行(Stream是无序的),默认为元素插入的顺序。顺序流下按照插入数据的顺序进行输出,并行流的时候流的遇到顺序得到保持。
@Test public void forEachOrdered() { List<Integer> list = Arrays.asList(2, 3, 4, 5, 6, 7); System.out.println("forEachOrdered顺序流下输出:"); list.parallelStream().forEachOrdered(f -> System.out.println("forEachOrdered顺序流下数据:" + f)); System.out.println(); System.out.println("forEachOrdered并行流下输出(流的遇到顺序得到保持):"); list.parallelStream().forEachOrdered(f -> System.out.println("forEachOrdered并行流下数据:" + f)); }
运行结果:
forEachOrdered顺序流下输出: forEachOrdered顺序流下数据:2 forEachOrdered顺序流下数据:3 forEachOrdered顺序流下数据:4 forEachOrdered顺序流下数据:5 forEachOrdered顺序流下数据:6 forEachOrdered顺序流下数据:7 forEachOrdered并行流下输出(流的遇到顺序得到保持): forEachOrdered并行流下数据:2 forEachOrdered并行流下数据:3 forEachOrdered并行流下数据:4 forEachOrdered并行流下数据:5 forEachOrdered并行流下数据:6 forEachOrdered并行流下数据:7
toArray 转成数组,也可以提供自定义数组生成器
@Test public void toArray() { Object[] animal= Stream.of("cat", "dog", "pig", "chicken", "duck").toArray(); for(Object a:animal){ System.out.println("数组里有:"+a); } }
运行结果:
数组里有:cat 数组里有:dog 数组里有:pig 数组里有:chicken 数组里有:duck
reduce方法是一个规约操作,所有的元素归约成一个。比如对所有元素求和,乘积等。这里实现了一个求和和乘积的方法,并指定了初始化的值分别为0和1(乘法指定1开始,不然没有意义).
@Test public void reduce() { int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).reduce(0, Integer::sum); System.out.println("1到10的和等于:" + sum); int product = Stream.of(1, 2, 3, 4, 5).reduce(1, (e1, e2) -> e1 * e2); System.out.println("1到5的乘积等于:" + product); }
运行结果:
1到10的和等于:55 1到5的乘积等于:120
collect 操作我们也使用了很多次了,就不过多详细介绍了
@Test public void collect() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT004", "王一林", "研发部", 30, 9000), new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包雅馨", "财务部", 25, 6000), new User("BAT007", "罗考聪", "测试部", 35, 7400.0)); //按年龄排序后转为list System.out.println("----------转list后的结果----------"); userList.stream().sorted(Comparator.comparingInt(User::getAge)).collect(Collectors.toList()).forEach(System.out::println); //按工资排序后转为set System.out.println("----------转set后的结果----------"); userList.stream().sorted(Comparator.comparingDouble(User::getSalary)).collect(Collectors.toCollection(LinkedHashSet::new)).forEach(System.out::println); //以员工的编号做为key,员工信息作为value转换为map System.out.println("----------以员工的编号做为key,员工信息作为value转换为map----------"); Map<String, User> collect = userList.stream().collect(Collectors.toMap(User::getId, u -> u)); collect.forEach((x, y) -> System.out.println(x + "->" + y)); //把名字用逗号分隔 System.out.println("----------名字拼接后结果----------"); String nameStr = userList.stream().map(User::getName).collect(Collectors.joining(",")); System.out.println(nameStr); System.out.println("----------按部门分组统计----------"); //按部门进行分组统计人数 Map<String, Long> groupingBy = userList.stream().collect(Collectors.groupingBy(User::getDepartment, Collectors.counting())); groupingBy.forEach((x, y) -> System.out.println(x + "->" + y)); //获取工资汇总信息 System.out.println("----------工资汇总信息----------"); DoubleSummaryStatistics statistics = userList.stream().collect(Collectors.summarizingDouble(User::getSalary)); System.out.println("最高工资:" + statistics.getMax()); System.out.println("最低工资:" + statistics.getMin()); System.out.println("工资总和:" + statistics.getSum()); System.out.println("平局工资:" + statistics.getAverage()); System.out.println("总记录数:" + statistics.getCount()); }
运行结果:
----------转list后的结果---------- User(id=BAT006, name=包雅馨, age=25, department=财务部, salary=6000.0) User(id=BAT005, name=梁南生, age=27, department=研发部, salary=8000.0) User(id=BAT004, name=王一林, age=30, department=研发部, salary=9000.0) User(id=BAT007, name=罗考聪, age=35, department=测试部, salary=7400.0) ----------转set后的结果---------- User(id=BAT006, name=包雅馨, age=25, department=财务部, salary=6000.0) User(id=BAT007, name=罗考聪, age=35, department=测试部, salary=7400.0) User(id=BAT005, name=梁南生, age=27, department=研发部, salary=8000.0) User(id=BAT004, name=王一林, age=30, department=研发部, salary=9000.0) ----------以员工的编号做为key,员工信息作为value转换为map---------- BAT004->User(id=BAT004, name=王一林, age=30, department=研发部, salary=9000.0) BAT007->User(id=BAT007, name=罗考聪, age=35, department=测试部, salary=7400.0) BAT005->User(id=BAT005, name=梁南生, age=27, department=研发部, salary=8000.0) BAT006->User(id=BAT006, name=包雅馨, age=25, department=财务部, salary=6000.0) ----------名字拼接后结果---------- 王一林,梁南生,包雅馨,罗考聪 ----------按部门分组统计---------- 测试部->1 财务部->1 研发部->2 ----------工资汇总信息---------- 最高工资:9000.0 最低工资:6000.0 工资总和:30400.0 平局工资:7600.0 总记录数:4
max方法根据指定的Comparator,返回一个Optional,该Optional中的value值就是Stream中最大的元素。
@Test public void max() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包雅馨", "财务部", 25, 6000), new User("BAT007", "罗考聪", "测试部", 35, 7400.0)); //筛选出年龄最大的员工信息 Optional<User> userOptional = userList.stream().max(Comparator.comparingInt(User::getAge)); //只是演示此处不做判断了 User user = userOptional.get(); System.out.println("年龄最大的员工信息:" + user); }
运行结果:
年龄最大的员工信息:User(id=BAT007, name=罗考聪, age=35, department=测试部, salary=7400.0)
min方法根据指定的Comparator,返回一个Optional,该Optional中的value值就是Stream中最小的元素。
@Test public void min() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包雅馨", "财务部", 25, 6000), new User("BAT007", "罗考聪", "测试部", 35, 7400.0)); //筛选出工资最低的员工信息 Optional<User> userOptional = userList.stream().min(Comparator.comparingDouble(User::getSalary)); //只是演示此处不做判断了 User user = userOptional.get(); System.out.println("工资最低的员工信息:" + user); }
运行结果:
工资最低的员工信息:User(id=BAT006, name=包雅馨, age=25, department=财务部, salary=6000.0)
count方法将返回Stream中元素的个数,一般用于流中间操作后的统计。
@Test public void count() { //初始化一个用户列表 List<User> userList = Arrays.asList( new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包雅馨", "财务部", 25, 6000), new User("BAT007", "罗考聪", "测试部", 35, 7400.0)); //统计年龄小于30的员工的个数 long count = userList.stream().filter(f -> f.getAge() < 30).count(); System.out.println("年龄小于30的员工的个数:" + count); }
运行结果:
年龄小于30的员工的个数:2
anyMatch方法按照指定的条件匹配到Stream中任意一个元素则返回true,否则返回false。
@Test public void anyMatch() { List<User> userList = Arrays.asList( new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包三雅", "财务部", 25, 6000), new User("BAT007", "罗考聪", "测试部", 35, 7400), new User("BAT008", "张伟杰", "测试部", 24, 7000)); //匹配任意一个年龄大于35岁的员工 boolean b = userList.stream().anyMatch(p -> p.getAge() > 35); System.out.println("匹配任意一个年龄大于34岁的员工:" + b); //匹配任意一个“张”姓的员工 boolean flag = userList.stream().anyMatch(p -> p.getName().startsWith("张")); System.out.println("匹配任意一个“张”姓的员工:" + flag); }
运行结果:
匹配任意一个年龄大于34岁的员工:false 匹配任意一个“张”姓的员工:true
allMatch方法按照指定的条件匹配Stream中所有的元素才返回true,否则返回false。
@Test public void allMatch() { List<User> userList = Arrays.asList( new User("BAT009", "胡俊伟", "研发部", 24, 4500), new User("BAT010", "胡健儿", "人事部", 23, 4000), new User("BAT011", "陶建文", "运维部", 25, 8000), new User("BAT012", "张萌萌", "行政部", 20, 3500)); //匹配所有人年龄都大于22岁 boolean b = userList.stream().allMatch(p -> p.getAge() > 22); System.out.println("所有人年龄都大于22岁:" + b); //匹配所有人年龄都大于18岁 boolean flag = userList.stream().allMatch(p -> p.getAge() > 18); System.out.println("所有人年龄都大于18岁:" + flag); }
运行结果:
所有人年龄都大于22岁:false 所有人年龄都大于18岁:true
noneMatch方法按照指定的条件,Stream中没有一个元素匹配得上才返回true,否则返回false。
@Test public void noneMatch() { List<User> userList = Arrays.asList( new User("BAT001", "胡昊天", "销售部", 28, 3500), new User("BAT002", "王大锤", "销售部", 27, 3000), new User("BAT003", "唐二鹏", "研发部", 32, 9900), new User("BAT004", "王一林", "研发部", 30, 9000), new User("BAT005", "梁南生", "研发部", 27, 8000)); //匹配没有一个“李”姓员工 boolean b = userList.stream().noneMatch(p -> p.getName().startsWith("李")); System.out.println("没有一个李姓员工:" + b); //匹配没有一个“胡”姓员工 boolean flag = userList.stream().noneMatch(p -> p.getName().startsWith("胡")); System.out.println("没有一个胡姓员工:" + flag); }
运行结果:
没有一个李姓员工:true 没有一个胡姓员工:false
findFirst方法用于获取Stream中的第一个元素的Optional,如果Stream为空,则返回一个空的Optional。
@Test public void findFirst() { List<User> userList = Arrays.asList( new User("BAT003", "唐二鹏", "研发部", 32, 9900), new User("BAT004", "王一林", "研发部", 30, 9000), new User("BAT005", "梁南生", "研发部", 27, 8000), new User("BAT006", "包雅欣", "财务部", 25, 6000) ); Optional<User> first = userList.stream().findFirst(); System.out.println("查找到的第一个员工信息:" + first.get()); }
运行结果:
查找到的第一个员工信息:User(id=BAT003, name=唐二鹏, age=32, department=研发部, salary=9900.0)
findAny方法用于获取Stream中的某个元素的Optional,如果Stream为空,则返回一个空的Optional,顺序流中总是返回第一个元素。
@Test public void findAny() { List<User> userList = Arrays.asList( new User("BAT006", "包雅欣", "财务部", 25, 6000), new User("BAT003", "唐二鹏", "研发部", 32, 9900), new User("BAT004", "王一林", "研发部", 30, 9000), new User("BAT005", "梁南生", "研发部", 27, 8000) ); Optional<User> userOptional = userList.stream().filter(p->p.getAge()<30).findAny(); userOptional.ifPresent(user -> System.out.println("查找到的任意一个员工信息:" + user)); }
运行结果:
查找到的任意一个员工信息:User(id=BAT006, name=包雅欣, age=25, department=财务部, salary=6000.0)
以上就是今天要讲的内容,主要介绍了Stream里一些常见的方法使用,平常还是需要多去看下API,加强练习,才能熟练,对我们后续写代码有极大的帮助。