java - 使用 Java Streams 从 Nested List 和 Outer List 收集数据

标签 java list java-8 hashmap java-stream

Class Package{
  Long packageId;
  String packageName;
  List<Service> serviceList;
}

Class Service{
  Long serviceId;
  String location;
}

List <Package> packageList

上面是我的类,要求是收集packageId来自外部列表 packageListserviceId来自内部列表(每个 ServicesPackage),其中 packageList.packageName == "Full"serviceList.location == "Japan" .另外,我需要知道这种记录是否存在。这是我到目前为止将数据收集到 HashMap 中所写的内容.

HashMap<String,Object> stringObjectHashMap = new HashMap<>();
boolean isFound = packageList.stream()
                .filter(package -> "Full".equalsIgnoreCase(package.getPackageName()))
                .peek(package ->stringObjectHashMap.put("packageId",package.getPackageId()))
                .flatMap(package -> package.getServiceList().stream())
                .filter(service -> service.getLocation().equalsIgnoreCase("Japan"))
                .peek(service -> stringObjectHashMap.put("serviceId",service.getServiceId()))
                .anyMatch(service -> service.getLocation().equalsIgnoreCase("Japan"));

问题是 Sonar 提示使用 peek()流里面。它说“根据其 JavaDocs,中间流操作 java.util.Stream.peek() “主要用于支持调试”目的。

谁能提出更好的解决方案?

示例输入:

[
    {
        "packageId": 13,
        "packageName": "Normal",
        "serviceList": [
            {
                "serviceId": "100",
                "location": "China"
            }
        ]
    },
    {
        "packageId": 10,
        "packageName": "Full",
        "serviceList": [
            {
                "serviceId": "100",
                "location": "Spain"
            }
        ]
    },
     {
        "packageId": 5,
        "packageName": "Full",
        "serviceList": [
            {
                "serviceId": "100",
                "location": "Japan"
            }
        ]
    }
]

预期输出,

"packageId": 5    //this is from outer list
"serviceId": 100  //this is from inner list

注意: "Full" 可以出现多次。以及位置"Japan"也可以在服务中多次出现。但是 packageName 的组合值为 "Full"和位置"Japan"只能出现一次。

最佳答案

通过使用 .flatMap(package -> package.getServiceList().stream())实际上,您将所有包的所有服务整合到一个巨大的流中,并将所有内容混在一起。

如果我对任务的理解正确,您想要选择名称为“Full”的所有包,然后,对于每个这样的包,选择该包列表中位置为“Japan”的任何服务,或者 null,如果这样的服务是不在那里。你可以 collect像这样的 map :

Map<String,Long> stringObjectMap = packageList.stream().filter(p -> "Full".equalsIgnoreCase(p.getPackageName()))
            .collect(Collectors.toMap(
                    Package::getPackageId,
                    p -> p.getServiceList().stream()
                            .filter(service -> "Japan".equalsIgnoreCase(service.getLocation()))
                            .map(Service::getServiceId)
                            .findFirst().orElse(null) //you might want to use a stand-in default value here instead of null
            ));

注意:这将导致 Map 的一些模糊实现,而不是真正的 HashMap,因此您可能需要进行调整。

就我个人而言,我发现使用常规 for 循环更容易解决此类情况。

关于java - 使用 Java Streams 从 Nested List 和 Outer List 收集数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72352454/

相关文章:

java - Java 8 流中的 arg 最大值?

java - XML + SQL : Any free standalone tool capable of injecting results of SQL queries into XML?

python统计前10名

java - 当键是字符串时如何在 Java 中创建范围映射

python - 删除 Python 列表列表中的重复项

python 求和列表列表的值

java - 如何从给定范围构建 LocalDate 列表?

Java 8 DateTimeFormatter for month in all CAPS 不工作

Java JTabbedPane 插入颜色

Java matchesAt() 在 C# 中等效