
本文旨在解决在使用Java Stream的groupingBy操作时,如何根据条件添加元素的问题。通过结合filtering Collector,可以在分组后对元素进行筛选,并避免副作用,从而实现更清晰、更高效的数据处理。本文将提供详细的代码示例和注意事项,帮助你更好地理解和应用这一技术。
在使用Java Stream的groupingBy操作时,有时需要在分组后根据特定条件添加或过滤元素。直接在mapping操作中进行条件判断并添加元素可能会导致代码可读性降低,甚至引入副作用。更优雅的解决方案是结合filtering Collector,在mapping之后对元素进行筛选。
filtering Collector允许你指定一个Predicate,只有满足该谓词的元素才会被保留在最终结果中。其基本结构如下:
.collect(Collectors.groupingBy(
e -> { /* 分类函数 */ },
Collectors.filtering(e -> { /* 谓词 */ },
Collectors.mapping(e -> { /* 映射函数 */ },
Collectors.toList())
)
))示例:
立即学习“Java免费学习笔记(深入)”;
假设我们有一个User类,其中包含stringSeq属性和一个ioTypes集合。我们希望根据stringSeq的前两个部分进行分组,并且只保留ioTypes不为空的User对象。
import java.util.*;
import java.util.stream.Collectors;
enum IOType {
NONE, TYPE1, TYPE2
}
class User {
private String stringSeq;
private Set<IOType> ioTypes;
public User(String stringSeq) {
this.stringSeq = stringSeq;
this.ioTypes = new HashSet<>();
}
public String getStringSeq() {
return stringSeq;
}
public Set<IOType> getIoTypes() {
return ioTypes;
}
public void addIoType(IOType ioType) {
this.ioTypes.add(ioType);
}
@Override
public String toString() {
return "User{" +
"stringSeq='" + stringSeq + '\'' +
", ioTypes=" + ioTypes +
'}';
}
}
public class GroupingByExample {
private static final String DELIMITER = "-";
private static final int MENU_IDX = 0;
private static final int GROUP_IDX = 1;
private static final int IO_TYPE_IDX = 2;
public static void main(String[] args) {
List<User> userList = new ArrayList<>();
userList.add(new User("MENU1-GROUP1-TYPE1"));
userList.add(new User("MENU1-GROUP1-TYPE2"));
userList.add(new User("MENU2-GROUP2-TYPE1"));
userList.add(new User("MENU2-GROUP2-TYPE2"));
userList.add(new User("MENU3-GROUP3-")); // Invalid data
userList.add(new User("MENU3-GROUP3-TYPE1"));
Map<String, List<User>> groupedUsers = userList.stream()
.collect(Collectors.groupingBy(
e -> {
String[] arr = e.getStringSeq().split(DELIMITER);
return String.join(DELIMITER, arr[MENU_IDX], arr[GROUP_IDX]);
},
Collectors.filtering(e -> {
String[] arr = e.getStringSeq().split(DELIMITER);
if(arr.length <= IO_TYPE_IDX) return false;
IOType ioType = IOType.valueOf(arr[IO_TYPE_IDX]);
e.addIoType(ioType);
return !e.getIoTypes().isEmpty();
},
Collectors.toList()
)
));
groupedUsers.forEach((key, value) -> {
System.out.println("Key: " + key);
value.forEach(System.out::println);
});
}
}在这个例子中,filtering Collector确保只有在ioTypes集合不为空的情况下,User对象才会被包含在最终的分组结果中。
需要注意的是,filter()操作和filtering() Collector的行为有所不同。如果某个Key对应的所有元素都不满足filtering() Collector的谓词,那么该Key仍然会出现在结果Map中,但其对应的值将是一个空列表。而如果使用filter()操作,则该Key根本不会出现在结果Map中。
在mapping()函数中修改函数参数(例如,直接修改User对象的ioTypes集合)是一种副作用。虽然在某些情况下可能不会导致问题,但通常不建议这样做,因为它会使代码更难理解和维护。
通过结合groupingBy和filtering Collector,可以更加灵活和清晰地处理分组后的数据。这种方法不仅可以根据条件筛选元素,还可以避免副作用,提高代码的可读性和可维护性。 在实际应用中,应根据具体需求选择合适的方案。如果需要在分组前过滤元素,可以使用filter()操作;如果需要在分组后根据条件筛选元素,则可以使用filtering() Collector。
以上就是使用Java Stream groupingBy时添加元素的正确姿势的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号