【问题标题】:Collection<Integer> cannot be converted to int while using Stream API使用 Stream API 时无法将 Collection<Integer> 转换为 int
【发布时间】:2021-12-19 18:26:02
【问题描述】:

我想做一个Map&lt;Person, Double&gt;,其中Double 是存储在另一个Map &lt;String, Integer&gt; 中的Integer 值的平均值,这是流元素的字段之一。

public Map<Person,Double> totalScores(Stream<CourseResult> programmingResults) {
    return 
        programmingResults.collect(Collectors.groupingBy(
            CourseResult::getPerson,
// And there is a problem, I want to get values from `Map <String, Integer>` 
// and do the `averagingInt`, but only get 
//`Bad return type in lambda expression: 
// Collection<Integer> cannot be converted to int`

            Collectors.averagingInt(
                s -> s.getTaskResults().values()
            )
        ));
}

我怎样才能以正确的方式获得这些值?

我正在使用一些类:

public class CourseResult {
    private final Person person;
    private final Map<String, Integer> taskResults;
    
    public CourseResult(final Person person, final Map<String, Integer> taskResults) {
        this.person = person;
        this.taskResults = taskResults;
    }
    
    public Person getPerson() {
        return person;
    }
    
    public Map<String, Integer> getTaskResults() {
        return taskResults;
    }
}

【问题讨论】:

  • 您必须添加 flatMap 才能从逻辑 Stream&lt;Collection&lt;Integer&gt;&gt;Stream&lt;Integer&gt;。不过,需要携带String 会增加一些复杂性。
  • 同一个Person真的有多个CourseResult实例,所以需要分组
  • @Holger 实际上没有。每个Person只有一个CourseResult
  • 那么,toMap 让您的生活更轻松(正如答案现在也指出的那样)。

标签: java lambda type-conversion java-stream


【解决方案1】:

如果保证输入流包含 CourseResult 具有唯一人员的实例(并且可能不需要对任务结果进行分组 + flatMapping),则使用 toMap 收集器可能就足够了:

public Map<Person,Double> totalScores(Stream<CourseResult> results) {
    return 
        results.collect(Collectors.toMap(
            CourseResult::getPerson,
            cr -> cr.getTaskResults().values() // Collection<Integer>
                .stream() // Stream<Integer>
                .collect(Collectors.averagingInt(Integer::intValue))
            )
        ));
}

【讨论】:

    【解决方案2】:

    请注意,values()Collection&lt;Integer&gt;。你不能这样平均。您可以使用平面映射Collector,将每组人员扁平化为整数,而不是CourseResult。之后,你可以通过恒等函数做一个平均。

    return programmingResults.collect(
        Collectors.groupingBy(
            CourseResult::getPerson,
            Collectors.flatMapping(s->s.getTaskResults().values().stream(),
                Collectors.averagingInt(x -> x)
                )
        )
    );
    

    编辑:如果每个Person 只有一个CourseResult,则不需要groupingBy。只需使用toMap 并使用另一个流计算平均值。

    return programmingResults.collect(
        Collectors.toMap(
            CourseResult::getPerson, 
            result -> result.getTaskResults().values()
                .stream().mapToInt(x -> x).average().orElse(0))
    );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-30
      • 2022-06-10
      • 2014-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      • 2016-12-26
      相关资源
      最近更新 更多