.传统集合处理需手动实现判空、筛选、去重等操作,步骤繁琐且易出问题。
.判空需重复编写if (list == null || list.isEmpty()),多集合判空时代码堆积严重。
.去重需创建Set并循环添加元素,自定义对象还需重写equals方法,操作复杂。// 传统集合处理:筛选启用用户、去重、求交集 public List<Long> getValidUserIds(List<User> userList, List<Long> roleAuthUserIds) { // 1. 判空用户列表,避免NPE,空则返回空集合 if (userList == null || userList.isEmpty()) { return Collections.emptyList(); } // 堆代码 duidaima.com // 2. 判空权限ID列表,避免NPE,空则返回空集合 if (roleAuthUserIds == null || roleAuthUserIds.isEmpty()) { return Collections.emptyList(); } // 3. 创建列表存储启用的用户 List<User> activeUsers = new ArrayList<>(); // 4. 循环遍历用户列表,筛选启用的非空用户 for (User user : userList) { if (user != null && user.isActive()) { activeUsers.add(user); } } // 5. 创建Set存储去重后的用户ID Set<Long> activeUserIds = new HashSet<>(); // 6. 循环提取启用用户的ID,利用Set实现去重 for (User user : activeUsers) { activeUserIds.add(user.getId()); } // 7. 创建列表存储最终有效的用户ID List<Long> validIds = new ArrayList<>(); // 8. 双重循环比对,获取用户ID与权限ID的交集 for (Long id : activeUserIds) { if (roleAuthUserIds.contains(id)) { validIds.add(id); } } // 9. 返回有效用户ID列表 return validIds; }
代码解析:
该方法需9步完成核心逻辑,步骤繁琐且耦合度高。
.首先通过两次独立if判断实现集合判空,若遗漏任一判空,后续循环会引发NPE。@Service public class UserService { // 1. 集合判空与非空校验 public void checkUserList(List<User> userList) { // 校验集合是否为空(支持List/Set/Map/Iterator等所有集合类型) if (CollUtil.isEmpty(userList)) { throw new IllegalArgumentException("用户列表不能为空"); } // 校验集合是否非空,等价于!CollUtil.isEmpty(userList),提升可读性 if (CollUtil.isNotEmpty(userList)) { System.out.println("用户列表共" + userList.size() + "人"); } } // 2. 集合为空时返回默认集合 public List<User> getDefaultUserList(List<User> userList) { // 创建默认用户列表,用于集合为空时返回 List<User> defaultUsers = Arrays.asList(new User(0L, "测试用户", true)); // 若userList为空(null或size=0),返回defaultUsers;否则返回原集合 return CollUtil.defaultIfEmpty(userList, defaultUsers); } // 3. 集合为null时返回不可变空集合 public List<Long> getEmptySafeUserIds(List<User> userList) { // 将null转换为不可变空集合,非null则保持原集合 List<User> safeList = CollUtil.emptyIfNull(userList); // 提取用户ID,即使集合为空也不会引发NPE return CollUtil.getFieldValues(safeList, "id", Long.class ); } }
代码解析:
checkUserList方法中,isEmpty统一处理多种集合类型的判空,无需针对List、Set单独编写判空逻辑,减少代码冗余。
isNotEmpty直接替代反向判断,避免!符号导致的可读性问题,代码更直观。@Service public class AuthService { // 1. 集合去重(支持简单类型与自定义对象) public List<User> distinctUsers(List<User> userList) { // 基于元素equals去重(自定义对象需重写equals和hashCode) List<User> simpleDistinct = CollUtil.distinct(userList); // 按用户ID去重,重复时保留第一个元素(无需重写equals方法) return CollUtil.distinct(userList, User::getId, false); } // 2. 计算两个集合的交集(获取共同元素) public List<Long> getCommonAuthIds(List<Long> userAuths, List<Long> roleAuths) { // 计算交集,自动处理集合判空,返回共同元素列表 // 示例:userAuths=[1,2,3,3],roleAuths=[3,4,5],结果为[3] return CollUtil.intersection(userAuths, roleAuths); } // 3. 计算并集与差集 public List<Long> getUnionAndSubtract(List<Long> userAuths, List<Long> roleAuths) { // 计算并集:保留两个集合的所有元素,重复次数取最大值 // 示例:userAuths=[1,2,3],roleAuths=[3,4,5],结果为[1,2,3,4,5] List<Long> unionAuths = CollUtil.union(userAuths, roleAuths); // 计算差集:获取userAuths中有但roleAuths中没有的元素 // 示例:userAuths=[1,2,3],roleAuths=[3,4,5],结果为[1,2] List<Long> subtractAuths = CollUtil.subtract(userAuths, roleAuths); // 按业务需求返回差集(可根据场景切换为并集) return subtractAuths; } }
代码解析:
distinct方法提供两种去重方式,满足不同场景。
基于元素equals去重时,需确保自定义对象重写equals和hashCode;按指定字段(如User::getId)去重时,无需修改对象结构,直接通过字段值判断重复,灵活性更高。@Service public class UserQueryService { // 1. 集合转Map(key为指定字段,value为元素) public Map<Long, User> getUserMapByIds(List<User> userList) { // 按用户ID作为key,User对象作为value生成Map // 注意:若ID重复,后续元素会覆盖前面元素(需确保key唯一) return CollUtil.fieldValueMap(userList, "id"); } // 2. 集合转Map(key重复时value为List) public Map<Long, List<User>> getUserListMapByIds(List<User> userList) { // 按用户ID作为key,value为相同ID的User列表,避免重复key导致的数据覆盖 return CollUtil.toListMap(userList, "id"); } // 3. 集合转字符串(用于前端展示) public String getUserNamesStr(List<User> userList) { // 提取用户列表中的“name”字段值,生成姓名列表 List<String> names = CollUtil.getFieldValues(userList, "name"); // 按“,”分隔姓名,拼接为字符串(示例结果:“张三,李四”) return CollUtil.join(names, ","); } // 4. 按自定义条件筛选元素 public List<User> getActiveAdultUsers(List<User> userList) { // 筛选非空、启用且年龄>18的用户,返回新集合(原集合不变) return CollUtil.filter(userList, user -> user != null && user.isActive() && user.getAge() > 18 ); } }
代码解析:
getUserMapByIds方法中,fieldValueMap无需手动循环put元素,直接通过“id”字段生成Map,后续按ID查询用户时,可通过map.get(1L)快速获取,效率从传统循环的O(n)提升至O(1)。但需注意key唯一性,避免数据覆盖。
getUserListMapByIds方法中,toListMap解决了key重复问题,将相同ID的用户存储为List,适用于一对多场景(如同一部门下的多个用户),避免传统Map因key重复导致的数据丢失。@Service public class ProjectApplicationService { // 1. 用户权限校验:筛选启用用户ID、去重、求交集 public List<Long> getValidUserIds(List<User> userList, List<Long> roleAuthUserIds) { // 第一步:筛选非空且启用的用户,排除无效数据 List<User> activeUsers = CollUtil.filter(userList, u -> u != null && u.isActive()); // 第二步:提取用户ID,并基于ID去重(避免重复用户) List<Long> activeUserIds = CollUtil.distinct(CollUtil.getFieldValues(activeUsers, "id", Long.class )); // 第三步:求用户ID与角色权限ID的交集,得到最终有效权限ID return CollUtil.intersection(activeUserIds, roleAuthUserIds); } // 2. 购物车添加商品:避免重复添加 public void addCartItem(List<CartItem> cart, CartItem item) { // 若商品非空且不在购物车中,则添加,返回是否添加成功 boolean isAdded = CollUtil.addIfAbsent(cart, item); if (isAdded) { System.out.println("商品添加成功"); } else { System.out.println("商品已在购物车中"); } } // 3. 商品下单次数统计 public Map<String, Integer> countProductOrders(List<String> productIds) { // 统计每个商品ID的出现次数,生成“商品ID-下单次数”的Map // 示例:productIds=["P001","P002","P001"],结果为{"P001":2,"P002":1} return CollUtil.countMap(productIds); } // 4. 集合分页:按页码和页大小切分数据 public List<User> getUsersByPage(List<User> userList, int pageNo, int pageSize) { // 按页码(从1开始)和页大小切分集合,自动计算起始/结束索引 // 示例:pageNo=1,pageSize=10,返回前10条数据;pageNo=2,返回11-20条 return CollUtil.page(pageNo, pageSize, userList); } }
代码解析:
用户权限校验场景中,通过filter、getFieldValues、distinct、intersection的组合,将传统20多行代码压缩为3行,逻辑清晰且无冗余。筛选、去重、交集运算均通过CollUtil方法实现,无需手动循环,性能更优。购物车添加商品场景中,addIfAbsent整合了“判空+contains判断+添加”的逻辑,无需手动编写if (item != null && !cart.contains(item)),代码更简洁,且避免了contains方法的重复调用。