Stream流概述
Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。
那么什么是Stream?
Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。
Stream可以由数组或集合创建,对流的操作分为两种:
- 中间操作,每次返回一个新的流,可以有多个。
- 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。
另外,Stream有几个特性:
- stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
- stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
- stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
Stream流的常用操作
1.List集合转Map
用到的是Stream中Collectors的toMap方法:Collectors.toMap
具体用法实例如下:
//声明一个List集合
List<Person> list = new ArrayList();
list.add(new Person("1001", "小A"));
list.add(new Person("1002", "小B"));
list.add(new Person("1003", "小C"));
System.out.println(list);
//将list转换map
Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));
System.out.println(map);
输出结果为:
注意:用Collectors的toMap方法转换List,一般会遇到两个问题。
一个是转换map,key重复问题;另一个是空指针异常,即转为map的value是null。
问题解决!!!
一、第一种问题报的错误如下:Duplicate key
原因是声明List集合时,有的Key重复,如图:
解决方法:(分三种,具体哪种看业务需求)
1.重复时用后面的value 覆盖前面的value
Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(key1 , key2)-> key2 ));
System.out.println(map);
2.重复时将前面的value 和后面的value拼接起来;
Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(key1 , key2)-> key1+","+key2 )); System.out.println(map);
3.重复时将重复key的数据组成集合
Map<String, List<String>> map = list.stream().collect(Collectors.toMap(Person::getId,
p -> {
List<String> getNameList = new ArrayList<>();
getNameList.add(p.getName());
return getNameList;
},
(List<String> value1, List<String> value2) -> {
value1.addAll(value2);
return value1;
}
));
System.out.println(map);
输出结果:
二:value为空导致 空指针
未重现此异常
TODO
2.对象List转另一个对象List
List<Student> studentList = persons.stream().map(v -> {
return new Student(v.getName(), v.getSex());
}).collect(Collectors.toList());
3.按某个属性统计分组
// 学生信息按照班级ID分组,返回map,key为班级ID,value为学生列表
Map<String, List<Student>> student = students.stream().collect(Collectors.groupingBy(Student::getClassId));
4.按某个属性分组并统计数量
//按城市分组统计count
Map<String, Long> map = employees.stream().collect(Collectors.groupingBy(Employee::getCity, Collectors.counting()));
5.按某个属性分组统计并计算平均值
Map<String, Double> map = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity, Collectors.averagingInt(Employee::getAge)));
6.按某个属性分组统计并计算总值
Map<String, Long> map = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity, Collectors.summingLong(Employee::getAmount)));
7.JSONArray和List互转
1.List转JSONArray
List list = new ArrayList();
JSONArray array= JSONArray.parseArray(JSON.toJSONString(list));
2.JSONArray转List
JSONArray array = new JSONArray();
List list = JSONObject.parseArray(array.toJSONString(), UserProfileInterval.class);
3.String转JSONArray
List list = JSONArray.parseArray(JSON.toJSONString(array), Population.class);
8.List分组
Map<String, List> dicCollect = dicAllList.stream().collect(Collectors.groupingBy(Dictionary::getDicType));
可以对结果进行映射,求和,统计
映射:
Map <String,List > collect = users.stream().collect(Collectors.groupingBy(User: :getEdu, //第二个参数对Map的value进行处理(映射)
Collectors.mapping(User: :getId, Collectors.toList())));
求和:
Map <String,Double> collect = users.stream().collect(Collectors.groupingBy(User: :getEdu, //对参数进行累计求和 Collectors.summingDouble(User: :getPrice)));
统计:
Map < String,Long > collect = users.stream().collect(Collectors.groupingBy(User: :getEdu, //获取count数量 Collectors.counting()));
统计:需要三个参数,第三个参数添加了对结果Map的生成方式,默认是HashMap
Map <String,Double > collect = users.stream().collect(Collectors.groupingBy(User: :getEdu, //决定map的生成方式,使用TreeMap TreeMap: :new, //对参数进行累计求和 Collectors.summingDouble(User: :getPrice)));