最近一直在忙老项目的升级改造,在处理数据的时候,突然想使用某个方法,隐隐约约记得,怎么写的却忘了。忘记了就要重新翻文档或搜索,非常麻烦。怎么办呢,那就抽时间整理一下吧,于是便有了此文。
List集合的各种处理
有一个List集合,里面装着UserInfo对象,对象里有用户uid、性别sex、年龄age、姓名userName等属性。
// 模拟一组用户数据
List<UserInfo> userInfoList = new ArrayList<UserInfo>(20);
UserInfo userInfo;
for(int i=1;i<10;i++){
userInfo = new UserInfo();
userInfo.setUserUid(i+ "");
userInfo.setUserName("用户"+i);
userInfo.setAge(i);
// 性别各一半
userInfo.setSex((byte) (i%2));
userInfoList.add(userInfo);
}
// 打印原数据
userInfoList.forEach(item->{logger.info("原数据:{}",item.toString());});
1、过滤List集合的对象,只保留sex为0的对象,并返回一个新的集合。
// 用法1:过滤 filter,只保留sex==0的数据
List<UserInfo> userInfoList1 = userInfoList.stream().filter(item->item.getSex()==0).collect(Collectors.toList());
userInfoList1.stream().forEach(item->{logger.info("保留的数据:{}",item.toString());});
打印结果:
22:24:24.052 [main] INFO com.test.other.TestStream - 原数据:UserInfo [userUid=4, age=4, sex=0, userName=用户4]
22:24:24.052 [main] INFO com.test.other.TestStream - 原数据:UserInfo [userUid=5, age=5, sex=1, userName=用户5]
22:24:24.052 [main] INFO com.test.other.TestStream - 原数据:UserInfo [userUid=6, age=6, sex=0, userName=用户6]
22:24:24.052 [main] INFO com.test.other.TestStream - 原数据:UserInfo [userUid=7, age=7, sex=1, userName=用户7]
22:24:24.052 [main] INFO com.test.other.TestStream - 原数据:UserInfo [userUid=8, age=8, sex=0, userName=用户8]
22:24:24.052 [main] INFO com.test.other.TestStream - 原数据:UserInfo [userUid=9, age=9, sex=1, userName=用户9]
22:24:24.065 [main] INFO com.test.other.TestStream - 保留的数据:UserInfo [userUid=2, age=2, sex=0, userName=用户2]
22:24:24.066 [main] INFO com.test.other.TestStream - 保留的数据:UserInfo [userUid=4, age=4, sex=0, userName=用户4]
22:24:24.066 [main] INFO com.test.other.TestStream - 保留的数据:UserInfo [userUid=6, age=6, sex=0, userName=用户6]
22:24:24.066 [main] INFO com.test.other.TestStream - 保留的数据:UserInfo [userUid=8, age=8, sex=0, userName=用户8]
// 使用filter对脏数据的过滤
userInfoList.stream().filter(Objects::nonNull).forEach(item->{logger.info("过滤脏数据:{}",item.toString());});
2、找出符合条件的第一个对象,没有返回null。
// 用法2:找出符合条件的第一个对象,没有返回null
userInfo = userInfoList.stream().filter(item->item.getAge()==8).findFirst().orElse(null);
logger.info("符合条件的第一个对象,没有返回null:{}",userInfo);
执行结果:
22:28:06.949 [main] INFO com.test.other.TestStream - 符合条件的第一个对象,没有返回null:UserInfo [userUid=8, age=8, sex=0, userName=用户8]
3、根据性别对集合进行分组,返回Map集合,每种性别个对应一个集合。
// 用法3:根据某个字段对集合排序,并以排序字段为key,存到map集合里 Collectors.groupingBy()
// 使用场景:把用户按照男女分成两组
Map<Byte, List<UserInfo>> userInfoMap = userInfoList.stream().collect(Collectors.groupingBy(item->item.getSex()));
logger.info("获取性别为0的数据数量:{}",userInfoMap.get((byte)0).size());
//
userInfoMap.keySet().forEach(item->logger.info("性别遍历{}",item));
执行结果:
22:30:26.901 [main] INFO com.test.other.TestStream - 获取性别为0的数据数量:4
22:30:26.906 [main] INFO com.test.other.TestStream - 性别遍历0
22:30:26.906 [main] INFO com.test.other.TestStream - 性别遍历1
// 如何把key变为String类型的
Map<String, List<UserInfo>> userInfoMap1 = userInfoList.stream().collect(Collectors.groupingBy(item->item.getSex().toString()));
logger.info("获取性别为0的数据数量:{}",userInfoMap1.get("0").size());
4、从集合中抽出对象的某一属性,并创建一个新的集合。
// 用法4:从对象集合里获取用户uid集合,map()+collect()
List<String> userUids = userInfoList.stream().map(item->item.getUserUid()).collect(Collectors.toList());
//List<String> userUids = userInfoList.stream().map(UserInfo::getUserUid).collect(Collectors.toList());
logger.info("从对象集合里获取用户uid集合:{}",userUids);
执行结果:
22:34:03.948 [main] INFO com.test.other.TestStream - 从对象集合里获取用户uid集合:[1, 2, 3, 4, 5, 6, 7, 8, 9]
5、从集合中抽出对象的某一属性,并创建一个新的集合,同时保证不重复。
// 用法5:获取单个数据的不重复集合,使用Set的集合特性
Set<Byte> sexs = userInfoList.stream().map(UserInfo::getSex).collect(Collectors.toSet());
logger.info("用户里的性别种类有:{}",sexs);
// // 用法5:获取单个数据的不重复集合,使用distinct方法
// List<Byte> sexs1 = userInfoList.stream().map(UserInfo::getSex).distinct().collect(Collectors.toList());
// logger.info("2用户里的性别种类有:{}",sexs1);
执行结果:
22:37:34.994 [main] INFO com.test.other.TestStream - 用户里的性别种类有:[0, 1]
6、获取集合中符合条件的对象,如果存在,并做一些事情。
// 用法6:对集合里符合条件的第一个对象的某个字段做些事情,ifPresent
userInfoList.stream().filter(item->item.getAge()==5).findFirst().ifPresent(item->item.setAge(15));
logger.info("被处理的数据:{}",userInfoList.stream().filter(item->item.getAge()==15).findFirst())
执行结果:
22:39:54.889 [main] INFO com.test.other.TestStream - 被处理的数据:Optional[UserInfo [userUid=5, age=15, sex=1, userName=用户5]]
7、从集合里匹配、或不匹配符合条件的对象属性,返回布尔值。
// 用法9:从对象集合里去查找是否存在某个元素为指定值,找到即返回
boolean isExists = userInfoList.stream().anyMatch(item->item.getAge()==15);
logger.info("是否存在年龄字段为5的数据:{}", isExists);
// noneMatch没有匹配的返回true,否则返回false
logger.info("队列里是否有年龄为20的:{}", userInfoList.stream().noneMatch(item->item.getAge()==20));
执行结果:
22:47:31.580 [main] INFO com.test.other.TestStream - 是否存在年龄字段为5的数据:false
22:47:31.585 [main] INFO com.test.other.TestStream - 队列里是否有年龄为20的:true
8、给一个对象,返回一个集合。
// 用法10:给一个对象,返回一个list集合,singleton返回set集合
List<String> str = Collections.singletonList("aaa");
logger.info("list集合:{}", str);
执行结果:
22:49:01.029 [main] INFO com.test.other.TestStream - list集合:[aaa]
9、抽取、排序、过滤、遍历组合使用。
// 对属性进行排序
userInfoList.stream()
.map(UserInfo::getSex)
.sorted(Comparator.comparing(obj -> obj))
.forEach(item->logger.info("数据:{}",item));
// 根据属性对对象进行排序
userInfoList.stream()
.filter(Objects::nonNull)
// 进行排序,按照pushDate升序
.sorted(Comparator.comparing(UserInfo::getSex))
.forEach(item->logger.info("数据:{}",item.toString()));
执行结果:
21:00:37.028 [main] INFO com.test.other.TestStream - 数据:0
21:00:37.032 [main] INFO com.test.other.TestStream - 数据:0
21:00:37.032 [main] INFO com.test.other.TestStream - 数据:0
21:00:37.032 [main] INFO com.test.other.TestStream - 数据:0
21:00:37.032 [main] INFO com.test.other.TestStream - 数据:1
21:00:37.033 [main] INFO com.test.other.TestStream - 数据:1
21:00:37.033 [main] INFO com.test.other.TestStream - 数据:1
21:00:37.033 [main] INFO com.test.other.TestStream - 数据:1
21:00:37.033 [main] INFO com.test.other.TestStream - 数据:1
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=2, age=2, sex=0, userName=用户2]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=4, age=4, sex=0, userName=用户4]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=6, age=6, sex=0, userName=用户6]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=8, age=8, sex=0, userName=用户8]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=1, age=1, sex=1, userName=用户1]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=3, age=3, sex=1, userName=用户3]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=5, age=5, sex=1, userName=用户5]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=7, age=7, sex=1, userName=用户7]
21:00:37.036 [main] INFO com.test.other.TestStream - 数据:UserInfo [userUid=9, age=9, sex=1, userName=用户9]
10、Collectors工具类的使用汇总
在上面的很多数据处理中,我们都离不开Collectors工具类,再把Collectors的使用汇总下:
// 1、把集合中对象的某个属性单独抽离出来作为一个新的集合
List<String> list = userInfoList.stream().map(UserInfo::getUserName).collect(Collectors.toList());
logger.info("list:{}",list);
// 2、返回一个不重复的集合
Set<String> set = userInfoList.stream().map(UserInfo::getUserName).collect(Collectors.toCollection(TreeSet::new));
logger.info("set:{}",set);
// 3、把一个集合的某个属性提前为一个字符串
String joined = userInfoList.stream()
.map(UserInfo::getUserName) //Object::toString
.collect(Collectors.joining(", "));
logger.info("joined:{}",joined);
// 4、对集合里对象的某个Integer属性求和
int total = userInfoList.stream()
.collect(Collectors.summingInt(UserInfo::getAge));
logger.info("total:{}",total);
// 5、分组,通过集合中某个对象的属性进行分组
Map<Byte, List<UserInfo>> bySex
= userInfoList.stream()
.collect(Collectors.groupingBy(UserInfo::getSex));
logger.info("bySex:{}",bySex);
// 6、计算,每种性别,各自年龄的总和
Map<Byte, Integer> totalBySex
= userInfoList.stream()
.collect(Collectors.groupingBy(UserInfo::getSex,Collectors.summingInt(UserInfo::getAge)));
logger.info("totalBySex:{}",totalBySex);
// 7、根据条件获取部分用户
Map<Boolean, List<UserInfo>> passingFailing =
userInfoList.stream()
.collect(Collectors.partitioningBy(s -> s.getAge() >= 5));
logger.info("passingFailing:{}",passingFailing);
11、求和,和10的求和有点区别。
// 用法11:求和
List<BigDecimal> numberList = new ArrayList<BigDecimal>();
numberList.add(new BigDecimal(10));
numberList.add(new BigDecimal(5));
logger.info("BigDecimal的list求和:{}", numberList.stream().reduce((x, y) -> x.add(y)).orElse(BigDecimal.ZERO));
// 把BigDecimal集合转换成String型集合
List<String> numberList1 = numberList.stream().map(BigDecimal::toString).map(String::trim).collect(Collectors.toList());
List<Integer> ls = new ArrayList<>();
ls.add(4);ls.add(2);ls.add(6);
logger.info("list先排序,转数组{},{}", ls.stream().sorted().mapToInt(i -> i).toArray(), ls.toArray());
Integer[] arr = new Integer[5];
arr[0] = 5;
logger.info("过滤前的数组{},对象:{}", arr,arr.toString());
// 过滤为null的数据,并返回一个新的数组
arr = Arrays.stream(arr).filter(Objects::nonNull).toArray(Integer[]::new);
logger.info("过滤后的数组{},对象{}", arr,arr.toString());
运行结果:
21:21:45.485 [main] INFO com.test.other.TestStream - BigDecimal的list求和:15
21:21:45.502 [main] INFO com.test.other.TestStream - list先排序,转数组[2, 4, 6],[4, 2, 6]
21:21:45.502 [main] INFO com.test.other.TestStream - 过滤前的数组[5, null, null, null, null],对象:[Ljava.lang.Integer;@3f8f9dd6
21:21:45.507 [main] INFO com.test.other.TestStream - 过滤后的数组[5],对象[Ljava.lang.Integer;@726f3b58
12、字符串数组,转为不重复集合。
// 字符串数组,转为不重复集合
String str1="aaa,bbb,ccc,ddd,aaa";
String[] arr = str1.split(",");
logger.info("不重复数组集合数量:{}", Arrays.stream(arr).distinct().count());
Set<String> set = Arrays.stream(arr).collect(Collectors.toSet());
// Arrays.asList(arr);
logger.info("不重复数组集合:{}", set);
List<String> str = Arrays.stream(arr).distinct().collect(Collectors.toList());
logger.info("不重复数组集合:{}", str);
// 将字符串集合转换为字符串
str1 = str.stream().collect(Collectors.joining("','", "('", "')"));
logger.info("拼接的字符串:{}", str1);
运行结果:
22:15:04.514 [main] INFO com.test.other.TestStream - 不重复数组集合数量:4
22:15:04.526 [main] INFO com.test.other.TestStream - 不重复数组集合:[aaa, ccc, bbb, ddd]
22:15:04.527 [main] INFO com.test.other.TestStream - 不重复数组集合:[aaa, bbb, ccc, ddd]
22:15:04.530 [main] INFO com.test.other.TestStream - 拼接的字符串:('aaa','bbb','ccc','ddd')
以上便是本次的整理,希望对你有帮助。
网友评论