繁体   English   中英

Stream 从两个列表直接到 SortedMap

[英]Stream from two lists directly to SortedMap

我正在尝试使用来自两个不同来源的两个ArrayList的流直接生成一个SortedMap 我的目标是让SortedMap将第二个列表中的Double属性存储为键,并将第一个列表中的 object 作为值,如果这些对象具有匹配的属性,则由助手 Object 检查。

到目前为止,我可以使用以下方法完成它:

SortedMap<Double, FirstObject> myMap = new TreeMap<>(Double::compareTo);

    List<FirstObject> myList = firstDao.get(someId).stream()
        .filter(firstobject -> secondDao.get(firstObject.getObjectId())
            .stream()
            .anyMatch(secondObject -> {
                if (Helper.check(secondObject).matches()) {
                    myMap.put(
                        secondObject.getEfficiency(), firstObject
                    );
                }
                return Helper.check(secondObject).matches();
            }))
        .collect(Collectors.toList());

我对使用该代码生成的myList没有用处,但到目前为止,这是我能够填充 Map 的唯一方法。 有没有一种方法可以直接填充到 SortedMap 而无需生成该列表?

而不是创建一个会导致副作用的filter ,您需要使用collect

一种方法是创建一个中间 Map ,它将 firstDao 返回的每个firstDaosecondDao返回的匹配对相关联。

然后在中间 map 的条目上创建 stream。 过滤掉带有空键(没有匹配对)的条目。 然后应用collect(Collectors.toMap())

NavigableMap<Double, FirstObject> myMap = firstDao.get(tableId).stream()
    .collect(Collectors.toMap( // creates a map `Map<Optional<Double>,FirstObject>`
        firstObject -> secondDao.get(firstObject.getObjectId()).stream()
            .filter(secondObject -> firstObject.getAttribute().equals(secondObject.getAttribute()))
            .findFirst()
            .map(FirstObject::getEfficiency),
        Function.identity(),
        (left, right) -> left // duplicated keys would appear when there are more then one object having no matching pair (the key would be an empty optional), so we need to guard against that case by providing a merge function to resulve duplicates
    ))
    .entrySet().stream()
    .filter(entry -> entry.getKey().isPresent())
    .collect(Collectors.toMap(
        entry -> entry.getKey().get(),    // extracting a key (efficiency)
        Map.Entry::getValue,              // extracting a value
        (left, right) -> { throw new AssertionError("duplicates are not expected"); }, // since the source is an intermediate map we don't expect duplicates
        TreeMap::new
    ));

解决此问题的另一种更简洁的方法是使用Collector.of()创建自定义收集器(整体逻辑保持不变):

NavigableMap<Double, FirstObject> myMap = firstDao.get(tableId).stream()
    .collect(Collector.of(
        TreeMap::new,                                          // mutable container of the collector
        (NavigableMap<Double, FirstObject> map, FirstObject firstObject) -> 
            secondDao.get(firstObject.getObjectId()).stream()  // population the mutable container
                .filter(secondObject -> next.getAttribute().equals(secondObject.getAttribute()))
                .findFirst()
                .map(FirstObject::getEfficiency)
                .ifPresent(efficiency -> map.put(efficiency, firstObject)),
        (left, right) -> { left.putAll(right); return left; } // merging containers in parallel, I'm assuming that there's no duplicates and hence there's no special policy
    ));

旁注:当您需要TreeMap时,最好使用NavigableMap作为抽象类型。 该接口扩展了SortedMap并提供了一系列SortedMap无法访问的方法。


解决OP发表的评论

问题中提供的此代码创建了通过 firstDao 检索的对象的firstDao ,如果谓词是肉类,则以下filter将更新 map myMap通过添加新条目(或替换现有条目的值), efficiency为第一个遇到的匹配 object 来自使用secondDao.get()作为源创建的 stream。

    .filter(firstobject -> secondDao.get().stream()
        .anyMatch(secondObject -> {
            if (someCondition) {
                myMap.put(secondObject.getEfficiency(), firstObject);
            }
            return someCondition;
    }))

anyMatch - 是一种短路操作,如果id相同但efficiency不同,它们将被忽略

上述解决方案中的这段代码的行为方式完全相同: findFirst将选择第一个object,其中someCondition将被评估为true (之后将单独处理空选项的情况,并且选项的equals/hashCode是委托到equals/hashCode实现其值,因此结果中没有差异的余地)。

firstObject -> secondDao.get().stream()
    .filter(secondObject -> someCondition)
    .findFirst()
    .map(FirstObject::getEfficiency)

我认为这是预期的行为,因为没有提到问题中提供的代码在某些方面出现故障,并且没有示例数据(这可能会导致相反的结论)。

因此,上述解决方案不会产生预期结果的说法与问题的当前 state 相矛盾,因为它基于原始代码的逻辑。

未指定所需结果之前(通过提供示例数据或描述原始代码有什么问题),我认为不可能改进答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM