根据两个List的内容生成SortedMap

kin*_*nad 2 java arraylist treemap sortedmap java-stream

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

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

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());
Run Code Online (Sandbox Code Playgroud)

我用该代码生成的代码没有用处myList,但到目前为止,这是我能够填充Map.

有没有一种方法可以直接填充到SortedMap而不需要生成该列表?

Ale*_*nko 5

filter您需要使用collect.

实现此目的的方法之一是创建一个中间 Map,它将 所返回的每个对象与 所firstDao返回的匹配对相关联secondDao

然后在中间映射的条目上创建一个流。过滤掉带有空键(没有匹配对)的条目。然后申请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
    ));
Run Code Online (Sandbox Code Playgroud)

解决此问题的另一种更简洁的方法是利用(整体逻辑保持不变)创建自定义收集器: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
    ));
Run Code Online (Sandbox Code Playgroud)

旁注:当您需要 a 时,TreeMap最好将其用作NavigableMap抽象类型。该接口扩展SortedMap并提供了一系列无法​​通过SortedMap.


解决OP发表的评论

问题中提供的代码创建了通过 检索的对象流,如果谓词是肉firstDao,则以下内容将通过添加新条目(或替换现有条目的值)与第一个遇到的条目filter来更新映射。使用作为源创建的流中的匹配对象。myMapefficiencysecondDao.get()

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

anyMatch- 是一个短路操作,如果有相同id但不同的efficiency,将被忽略

上面解决方案中的这段代码的行为方式完全相同:findFirst将选择将要评估的第一个对象(随后将单独处理具有空可选的情况,并且可选的委托是其值的实现,因此结果中没有差异的余地)。someConditiontrueequals/hashCodeequals/hashCode

firstObject -> secondDao.get().stream()
    .filter(secondObject -> someCondition)
    .findFirst()
    .map(FirstObject::getEfficiency)
Run Code Online (Sandbox Code Playgroud)

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

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

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