网上有很多关于stream流的文章和案例分析,我只记录自己在实际开发中用过的,慢慢更新记录。 ps:用的jdk17,用toList()代替collect(Collectors.toList())
1.以逗号分割的字符串转list
// 以逗号分割的字符串转list
String userId = "25421,84521,78495,23584";
List<String> userIdList = Arrays.stream(userId.split(",")).collect(Collectors.toList());
userIdList.stream().forEach(System.out::println);
// jdk17 可以直接用toList()代替
System.out.println("------------------------");
userIdList = Arrays.stream(userId.split(",")).toList();
userIdList.stream().forEach(System.out::println);
// 正在使用以上字符串是没有问题的,但如果是客户自己输入,可能会出现以下情况
userId = "25421,84521,78495,23584,";
// 这种情况,如果我们不做任何业务逻辑其实也不影响什么,如果这个字符串是客户手机号,一般情况会使用正则校验手机号
// 这时,我会考虑到代码健壮性,会这样操作,避免因为一个逗号(,),出现其他问题
if (userId.endsWith(",")) {
// todo 这里可以根据实际业务,抛出异常或者是直接截取
userId = userId.substring(0, userId.length() - 1);
}
userIdList = Arrays.stream(userId.split(",")).toList();
System.out.println("------------------------");
userIdList.stream().forEach(System.out::println);
// 如果是将这个字符串插入到数据库中,那么还需要考虑空字符情况,
// 避免出现通过某个后台管理系统配置的数据,导致客户端在使用时,出现异常
userId = "25421,,78495,23584";
userIdList = Arrays.stream(userId.split(",")).filter(s -> StringUtils.isNoneBlank(s.trim())).toList();
System.out.println("------------------------");
userIdList.stream().forEach(System.out::println);
// 但对于这种情况,现在还用的是foreach todo 我还没找到用stream流如何解决,
List<String> list = new LinkedList<>();
userId = "25421 ,78495,23584";
for (String s : userId.split(",")) {
list.add(s.trim());
}
System.out.println("------------------------");
list.stream().forEach(System.out::println);
2.将List转为以逗号分割的字符串
// 将List转为以逗号分割的字符串
List<String> list = Arrays.asList("25421", "84521", "78495", "23584");
// 在我接触Stream流以前,我都是这样处理的
StringBuffer sb = new StringBuffer();
String userId = "";
for (String s : list) {
sb.append(s).append(","); // 逗号可换成其他符号
}
userId = sb.toString();
if (sb.toString().endsWith(",")) {
userId = sb.substring(0, sb.length() - 1);
}
System.out.println(userId);
System.out.println("------------------------");
// 认识Stream流之后
if (CollectionUtils.isNotEmpty(list)) {
userId = list.stream().collect(Collectors.joining(","));
}
System.out.println(userId);
// 有时候还是List<Map<String,Object>>类型的数据
// 认识Stream之前也是要遍历用StringBuffer
List<Map<String, Object>> userIdMapList = new LinkedList<>();
Map<String, Object> userIdMap1 = new HashMap<>();
Map<String, Object> userIdMap2 = new HashMap<>();
Map<String, Object> userIdMap3 = new HashMap<>();
Map<String, Object> userIdMap4 = new HashMap<>();
userIdMap1.put("userId", "25421");
userIdMap2.put("userId", "84521");
userIdMap3.put("userId", "78495");
userIdMap4.put("userId", "23584");
userIdMapList.add(userIdMap1);
userIdMapList.add(userIdMap2);
userIdMapList.add(userIdMap3);
userIdMapList.add(userIdMap4);
// 有空的过滤下value为null
userId = userIdMapList.stream().
map(item -> (String) item.get("userId")).collect(Collectors.joining(","));
System.out.println("------------------------");
System.out.println(userId);
3.Stream流分组结合排序
// 之前有个任务,按产品渠道分组后在按照产品类型从小到大排序,有表A、表B 通过主外键关联,由于没有设计实体类,直接用List<Map>>代替
List<Map<String, Object>> channelMapList = new LinkedList<>();
// 手动造数
String[] channelS = {"A", "B", "C", "D"};
String[] productS = {"1", "3", "4", "2"};
for (String channel : channelS) {
for (String product : productS) {
Map<String, Object> channelMap = new HashMap<>();
channelMap.put("channel", channel);
channelMap.put("product", product);
channelMapList.add(channelMap);
}
}
channelMapList.stream().forEach(System.out::println);
// 分组
Map<String, List<Map<String, Object>>> channelMap = channelMapList.stream().collect(Collectors.groupingBy(item -> (String) item.get("channel")));
System.out.println("------------------------");
System.out.println(channelMap);
// 按产品排序
Set<String> keySet = channelMap.keySet();
for (String key : keySet) {
List<Map<String, Object>> product = channelMap.get(key).stream().sorted(Comparator.comparing(o -> o.get("product").toString())).toList();
channelMap.put(key, product);
} // 貌似还是不智能
System.out.println("------------------------");
System.out.println(channelMap);
// 智能一些操作,先排序在分组
channelMap = channelMapList.stream().sorted(Comparator.comparing(o -> o.get("product").toString())).collect(Collectors.groupingBy(item -> (String) item.get("channel")));
System.out.println("------------------------");
System.out.println(channelMap);
// 总结:其实stream流这种模式写,比较简洁,但从打印结果来看,会出现一些额外参数,
// 比如在分组后每个Map<key,List<Map>>中,List<Map>还存在channel这个属性值,或者其他一些前端用不上属性值,在实际开发中,可以在动态调整下
// ps:像上面案例中,还会存在漏洞,比如排序用toString,如果该属性值为null,会导致空指针异常,所以实际开发中,还需要考虑其他因素
4.List集合收集
List<String> list = Arrays.asList("25421", "84521", "78495", "23584");
List<Map<String, String>> userList = list.stream().map(s -> {
Map<String, String> userMap = new HashMap<>();
userMap.put("userId", s);
userMap.put("userPhone", getUserPhoneRandom()); // 用随机数代替
return userMap;
}).filter(item -> ObjectUtils.isNotEmpty(item)).toList();
System.out.println(userList);
private String getUserPhoneRandom() {
String phone = "181"; // 省时间
SecureRandom random = new SecureRandom();
for (int i = 0; i < 8; i++) {
phone += random.nextInt(10);
}
return phone;
}
总结:由于我们项目中使用Map次数高于实体类,故案例都是用的Map,以后可试着写一下用实体类