Skip to content

Java8 filter的坑

对于Java8中的Stream用法,大家肯定再熟悉不过了。

我们通过对集合Stream操作,可以实现:遍历集合、过滤数据、排序、判断、转换集合等等,N多功能。

这里重点说说数据的过滤。

在没有Java8之前,我们过滤数据一般是这样做的:

java
public List<User> filterUser(List<User> userList) {
    if(CollectionUtils.isEmpty(userList)) {
        return Collections.emptyList();
    }
    
    List<User> resultList = Lists.newArrayList();
    for(User user: userList) {
        if(user.getId() > 1000 && user.getAge() > 18)   {
           resultList.add(user);
        }
    }
    return resultList;
}

通常需要另一个集合辅助完成这个功能。

但如果使用Java8的filter功能,代码会变得简洁很多,例如:

java
public List<User> filterUser(List<User> userList) {
    if(CollectionUtils.isEmpty(userList)) {
        return Collections.emptyList();
    }
    
    return userList.stream()
    .filter(user -> user.getId() > 1000 && user.getAge() > 18)
    .collect(Collectors.toList());
}

代码简化了很多,完美。

但如果你对过滤后的数据,做修改了:

java
List<User> userList = queryUser();
List<User> filterList = filterUser(userList);
for(User user: filterList) {
   user.setName(user.getName() + "测试");
}

for(User user: userList) {
   System.out.println(user.getName());
}

你当时可能只是想修改过滤后的数据,但实际上,你会把元素数据一同修改了。

意不意外,惊不惊喜?

其根本原因是:过滤后的集合中,保存的是对象的引用,该引用只有一份数据。

也就是说,只要有一个地方,把该引用对象的成员变量的值,做修改了,其他地方也会同步修改。

如下图所示:

filter

粤ICP备20009776号