Java 8 Stream筛选两个对象列表:获取未付费用户列表问题求助
问题排查与修复方案
首先咱们来揪出你代码里的核心问题:你只创建了一个User实例,然后反复修改它的属性并两次添加到列表里。这就导致users列表里的两个元素其实是同一个对象的引用,最后一次修改的userName = "ABC"会覆盖之前的"XYZ"——说白了,你的users列表里两个元素的用户名全都是"ABC",这就是为什么过滤后会返回所有元素。
第一步:修复User对象的创建逻辑
你得为每个用户创建独立的User实例,不能重复用同一个对象:
List<User> users = new ArrayList<>(); // 第一个用户XYZ,单独创建实例 User u1 = new User(); u1.age = "12"; u1.userName = "XYZ"; users.add(u1); // 第二个用户ABC,再创建一个新实例 User u2 = new User(); u2.age = "12"; u2.userName = "ABC"; users.add(u2);
第二步:优化过滤逻辑(可选但推荐)
你当前的过滤逻辑每次遍历用户时都要完整扫一遍paids列表,数据量大的时候性能会拖后腿。建议先把已付费用户的用户名提取到HashSet里,这样判断是否存在的速度会快很多:
// 先把所有已付费用户的用户名收集到Set中 Set<String> paidUserNames = paids.stream() .map(PaidUser::getUserName) .collect(Collectors.toSet()); // 过滤未付费用户 List<User> unpaidUsers = users.stream() .filter(user -> !paidUserNames.contains(user.getUserName())) .collect(Collectors.toList());
完整修复后的代码
class User { private String userName; private String age; public String getAge() { return age; } public String getUserName() { return userName; } } class PaidUser { private String userName; private double amt; public String getUserName() { return userName; } } public class Main { public static void main(String[] args) { List<User> users = new ArrayList<>(); User u1 = new User(); u1.age = "12"; u1.userName = "XYZ"; users.add(u1); User u2 = new User(); u2.age = "12"; u2.userName = "ABC"; users.add(u2); List<PaidUser> paids = new ArrayList<>(); PaidUser paid = new PaidUser(); paid.userName = "XYZ"; paid.amt = 1; paids.add(paid); Set<String> paidUserNames = paids.stream() .map(PaidUser::getUserName) .collect(Collectors.toSet()); List<User> unpaidUsers = users.stream() .filter(user -> !paidUserNames.contains(user.getUserName())) .collect(Collectors.toList()); // 验证输出:只会打印ABC unpaidUsers.forEach(user -> System.out.println(user.getUserName())); } }
这样修改后,unpaidUsers里就只会包含用户名是"ABC"的用户啦。
内容的提问来源于stack exchange,提问作者Abdul Jabbar
相关产品推荐
相关产品推荐

