jdk1.8新特性Stream集合详细操作

一.Stream流的介绍

1.stream是对集合的增强操作

通过将集合转换为一种叫做”流“的元素序列,通过声明方式,对集合中的每个元素进行一系列并行或串行的流水线操作

2.stream的特点

  • 不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果;
  • 不会改变数据源,通常情况下会产生一个新的集合;
  • 具有延迟执行特性,只有调用终端操作时,中间操作才会执行。

3.流的操作:Stream操作大体上分为两步,中间操作和终止操作

在这里插入图片描述

中间操作中间操作会产生另一个流。因此中间操作可以用来创建执行一系列动作的管道。一个特别需要注意的点是:中间操作不是立即发生的。相反,当在中间操作创建的新流上执行完终端操作后,中间操作指定的操作才会发生。所以中间操作是延迟发生的,中间操作的延迟行为主要是让流API能够更加高效地执行。

终端操作会消费流,这种操作会产生一个结果的,如果一个流被消费过了,那它就不能被重用的。

二.创建Stream对象

//方式1: Arrays.stream方法创建Stream对象
Integer[] arr = { 1, 2, 3, 4, 5, 6 }; //数组对象
Stream<Integer> stream1=Arrays.stream(arr);

//方式2: Stream.of方法
Stream<Integer> stream2=Stream.of(1,2,3,4,5);

//方式3:集合
List<Integer> list=Arrays.asList(1,2,3,4);
//普通流
Stream<Integer> stream01=list.stream();
//并行流(并行能力,多线程使用)
Stream<Integer> stream02=list.parallelStream();

三.中间操作:生成一个新Stream

实例集合:

@Data
public class Student {
   private String name;
    private int age;
    private Date birthday;
    private String address;
    private String sex;
    private double score;
}

//集合
List<Student> list= new ArrayList<>();

1.filter:过滤,筛选出符合条件的数据被留下来

        实际上是条件返回true则保存数据,返回false则去除数据

//过滤出条件返回值为true的元素,过滤出"姓李且18岁的学生"
List<Student> result = list.stream().filter(e -> e.getName().endsWith("李") && e.getAge() == 18).collect(Collectors.toList());

2.distinct:去掉重复值,将不重复的元素生成一个新的Stream

        默认对基本数据类型和String类型去重,如果是自定义类型的元素,则如果想实现去重,必须重写 equals()方法与hashCode()方法

List<String> list=Arrays.asList("a","b","c","a");
//只能对集合的整个元素去重
List<String> collect = list.stream().distinct().collect(Collectors.toList());

3.map:转换,遍历Stream中每一个元素,对元素操作后,返回结果

//获取集合中元素某字段的集合,取学生岁数的集合
List<Integer> collect = list.stream().map(Student::getAge).collect(Collectors.toList());

4.peek消费操作:如果想对数据进行某些操作,如:读取、编辑修改等。

        peek函数是一种特殊的map函数,当函数没有返回值或者参数就是返回值的时候可以使用peek函数,不需要返回值

//修改名字为name+age
List<Student> collect = list.stream().peek(e -> e.setName(e.getName() + e.getAge())).collect(Collectors.toList());

5.flatMap :处理二维集合(集合中元素是集合),将每一个元素拆分成一个新的流

List<List<Student>> lists=new ArrayList<>();
List<Student> collect2 = lists.stream().flatMap(Collection::stream).collect(Collectors.toList());
        

6.limit:截取集合前max个元素,返回一个不超过给定长度的新Stream对象

//截取集合前3个元素
List<Student> limit = list.stream().limit(3).collect(Collectors.toList());

7.skip:跳过前n个元素,返回剩下的

//跳过集合前2个元素
List<Student> limit = list.stream().skip(2).collect(Collectors.toList());

8.sorted:排序

//一.list排序
//单字段排序,年纪升序(不做空字段处理,如果字段为空会报错)
List<Student> collect1 = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
//多字段升序,先以年纪升序,再成绩升序
List<Student> collect2 = list.stream().sorted(Comparator.comparing(Student::getAge).thenComparing(Student::getScore)).collect(Collectors.toList());

//降序有两种写法,1:直接降序排列,2.先以Age升序,结果再进行降序
List<Student> collect3 = list.stream().sorted(Comparator.comparing(Student::getAge,Comparator.reverseOrder())).collect(Collectors.toList());
List<Student> collect4=list.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList());

//对排序字段空值处理,有空字段的元素放在集合开始/末尾
//nullsFirst(Comparator<? super T> comparator)参数:此方法接受单个参数比较器,该比较器是用于比较非空值的比较器
List<Student> collect5 = list.stream().sorted(Comparator.comparing(Student::getAge, Comparator.nullsFirst(Integer::compareTo))).collect(Collectors.toList());

//排序的另一种写法,在排序中,null元素将排在第一位。非空元素的顺序将由传递给nullsFirst方法的比较器决定。
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName)));
Collections.sort(list, Comparator.nullsFirst(Comparator.comparing(Student::getName).reversed()));

//二.map排序
//以key排序升序,若velue排序相同
Map<String,String> oldmap=new HashMap<>();
//1.创建新集合排序后放数据,无返回值 2.排序后使用.collect(Collectors.toMap(...))转map后直接返回
Map<String,String> newmap=new HashMap<>();
oldmap.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(e-> newmap.put(e.getKey(),e.getValue()));

四.终端操作:返回的结果,终端操作此流的生命周期结束。

1.forEach() 遍历流中每一个元素,会关闭流

        forEach 不能修改自己包含的本地变量值,也不能用 break/return 之类的关键字提前结束循环。

2.findFirst(),findAny()

        查找操作,查找第一个、任何一个,返回的类型为Optional。常用于查询集中符合条件的元素,如果流是空的,则返回空

        大多数情况下,数据量不大的情况下,findAny()也会返回第一个元素,此时效果与findFirst()一致

3.allMatch,anyMatch,noneMatch

        allMatch 要求Stream中所有元素都满足条件才返回true

        anyMatch, 只要有1个元素满足就返回true

        noneMatch 要求所有的元素都不满足条件才返回true

//每个学生年纪都为18才返回true
boolean flag = list.stream().allMatch(e -> e.getAge() == 18);
//任意一个学生是18,则返回true
boolean flag = list.stream().anyMatch(e -> e.getAge() == 18);
//学生年纪没有一个是18 ,则返回true
boolean flag = list.stream().noneMatch(e -> e.getAge() == 18);

4.reduce:将整个数据流的值规约为一个值,其中count、min、max底层就是使用reduce,也可用于字符串连接

// 字符串连接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
// 集合累加求和,另一写法reduce(0,Integer::sum)
int sum2=Stream.of(1,2,3,4,5).reduce((t,u)->t+u).get();
//输出最大值,另一写法reduce(Integer::max)
int max=Stream.of(1,2,3,4,5).reduce((t,u)-> t>=u? t:u).get();

2> 有2个参数 T reduce(T identity, BinaryOperator<T> accumulator)
多一个泛型T,实际上相对于在计算值的时候多一个初始化的值
int sum3=Stream.of(1,2,3,4,5).reduce(0,(t,u)->t+u);

5.min、max最值操作:需要自定义比较器,返回数据流中最大、最小的值

//查年纪最大的
Optional<Student> max = list.stream().max(Comparator.comparing(Student::getAge));
if (max.isPresent()) {
    Student student = max.get();
    }

6.count : 返回Stream中元素的个数

7.toArray数组操作:将数据流的元素转换成数组。

List<String> list=Arrays.asList("a","b","c","a");     
//返回数组 
String[] newArr=list.stream().toArray(String[]::new);

8.collect收集操作,将流规约并返回结果

        Collectors作为参数提供了非常多收集器 ,java.util.stream.Collectors,是从JDK1.8开始新引入的一个类。Collectors实现了各种有用归约的操作,例如类型归类到新集合、根据不同标准汇总元素等

8.1. 将集合中元素按照类型、条件过滤等归类,存放到指定类型的新数组,集合,List、Map、Set、Collection或者ConcurrentMap

  • Collectors.toList()

  • Collectors.toMap()

  • Collectors.toSet()

  • Collectors.toCollection()

  • Collectors.toConcurrentMap()

//返回list
List<String> list2=list.stream().collect(Collectors.toList());
//返回Stack
Stack<String> stack=list.stream().collect(Collectors.toCollection(Stack::new));

//转换为map,key=age,velue=Score,key相同时就比较score,大的覆盖
//如果条件为(key1,key2) -> key1表示key相同时以前key为准
//如果不处理key则key不能相同,否则报错
Map<Integer, Double> collect6 = list.stream().collect(Collectors.toMap(Student::getAge, Student::getScore, (score1, score2) -> score1 > score2 ? score1 : score2));
    

8.2. groupingBy:按条件分组,分组后,返回的是一个Map集合,其中key作为分组条件,value作为对应分组结果

  • Collectors.groupingBy(…):普通分组。

  • Collectors.groupingByConcurrent(…):线程安全的分组。

// groupingBy(按什么字段分组,去Collectors找相关的方法)
//简单分组,按年纪分组
Map<Integer, List<Student>> collect1 = list.stream().collect(Collectors.groupingBy(Student::getAge));
//velue转换为set集合
Map<Integer, Set<Student>> collect2 = list.stream().collect(Collectors.groupingBy(Student::getAge,Collectors.toSet()));

//按性别分组并统计人数
Map<String,Long> map1=list.stream().collect(Collectors.groupingBy(Student::getSex,Collectors.counting()));
//按性别分组,求年纪之和
Map<String, Integer> collect = list.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.summingInt(Student::getAge)));

//按性别分组,并统计名字作为值
Map<String, List<String>> collect1 = list.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.mapping(Student::getName, Collectors.toList())));
        

//按照性别分组,将分数进行聚合运算
//IntSummaryStatistics,DoubleSummaryStatistics,LongSummaryStatistics数据统计类,可在分组后对
//聚合数据count,min,max,sum和average
Map<String, DoubleSummaryStatistics> map2 =list.stream().collect(Collectors.groupingBy(Student::getSex,Collectors.summarizingDouble(Student::getScore)));
        System.out.println("所有男的总学分:" + map2.get('男').getSum());
        System.out.println("男生最高学分:" + map2.get('男').getMax());
        System.out.println("男生最低学分:" + map2.get('男').getMin());
        System.out.println("男生的平均分:" + map2.get('男').getAverage());
        System.out.println("男生的个数:" + map2.get('男').getCount());

8.3.分区,是分组的特殊情况,​​​​​​partitioningBy(…)

        该方法实质是在做二分组,将符合条件、不符合条件的元素分组到两个key分别为truefalseMap中,从而我们能够得到符合和不符合的分组新集合。

//人名按照中、英文名进行分区
Map<Boolean, List<Student>> collect3 = list.stream().collect(Collectors.partitioningBy(e -> e.getName().matches("^[a-zA-Z]*")));
//取英文集合
List<Student> students = collect3.get(true);
//取中文集合
List<Student> students1 = collect3.get(false);

8.4. 最值

        按照某个属性查找出最大或最小值元素,并且基于Comparator接口来对其进行比较,返回一个Optional对象,并结合Optional.isPresent()判断并取得最大或最小值

  • Collectors.maxBy(…):最大值。
  • Collectors.minBy(…):最小值。
//查找年纪最大的人
Optional<Student> collect4 = list.stream().collect(Collectors.maxBy(Comparator.comparingInt(Student::getAge)));
if (collect4.isPresent()) {//防止空指针
     Student student = collect4.get();
    }

8.5. 累加、汇总,平均值

        用来完成累加计算、数据汇总(总数、总和、最小值、最大值、平均值)操作。

  • Collectors.summingInt/Double/Long(…):按照某个属性求和。
  • Collectors.summarizingInt/Double/Long(…):按照某个属性的数据进行汇总,得到其总数、总和、最小值、最大值、平均值。
//单个属性求和,年纪求和
Integer collect5 = list.stream().collect(Collectors.summingInt(Student::getAge));
//单属性统计,年纪统计IntSummaryStatistics{count=10, sum=564, min=18, average=20.000000, max=22}
IntSummaryStatistics collect6 = list.stream().collect(Collectors.summarizingInt(Student::getAge));
        
//单属性均值,平均年龄
 Double v = list.stream().collect(Collectors.averagingDouble(Student::getAge));

8.6. 连接
        将元素以某种规则连接起来,得到一个连接字符串。

  • Collectors.joining():字符串直接连接。
  • Collectors.joining(CharSequence delimiter):按照字符delimiter进行字符串连接。
  • Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix):按照前缀prefix,后缀suffix,并以字符delimiter进行字符串连接。
//名字按照","分割连接: "小红,小明"
String collect7 = list.stream().map(Student::getName).collect(Collectors.joining(","));
        

8.7.集合对象属性去重

//根据对象单/多属性去重,并转换为list
ArrayList<Student> collect7 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new));
ArrayList<Student> collect8 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName).thenComparing(Student::getAge))), ArrayList::new));
  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以按照以下方式实现: 1. 往HashMap集合中添加若干元素,并获取Map中的所有key并使用迭代器遍历输出每个key: ```java import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class Main { public static void main(String[] args) { // 创建HashMap集合 Map<String, Integer> map = new HashMap<>(); // 添加元素到HashMap集合 map.put("A", 1); map.put("B", 2); map.put("C", 3); // 获取Map中的所有key并使用迭代器遍历输出每个key Iterator<String> iterator = map.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); System.out.println(key); } } } ``` 2. 获取上述Map集合的所有value,并使用增强for和JDK 1.8开始之后的Lambda表达式输出每个value: ```java import java.util.HashMap; import java.util.Map; public class Main { public static void main(String[] args) { // 创建HashMap集合 Map<String, Integer> map = new HashMap<>(); // 添加元素到HashMap集合 map.put("A", 1); map.put("B", 2); map.put("C", 3); // 使用增强for循环遍历输出每个value for (Integer value : map.values()) { System.out.println(value); } // 使用Lambda表达式遍历输出每个value map.values().forEach(System.out::println); } } ``` 以上代码中,我们首先创建一个HashMap集合,并使用put方法往集合中添加若干元素。然后,使用keySet方法获取Map中的所有key,并通过迭代器遍历输出每个key。接下来,使用values方法获取Map集合的所有value,并使用增强for循环和Lambda表达式分别遍历输出每个value。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值