当前位置: 首页 > 知识库问答 >
问题:

Java流平均值

阙俊友
2023-03-14

我需要使用流创建两个方法。返回每个任务平均分数的方法。

    public Map<String, Double> averageScoresPerTask(Stream<CourseResult> results) {}

以及一种返回平均得分最高的任务的方法。

    public String easiestTask(Stream<CourseResult> results) {}

我只能修改这两种方法。

这是CourseResult课程

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;
    }
}

以及创建CourseResult对象的方法。

private final String[] programTasks = {"Lab 1. Figures", "Lab 2. War and Peace", "Lab 3. File Tree"};
private final String[] practicalHistoryTasks = {"Shieldwalling", "Phalanxing", "Wedging", "Tercioing"};

private Stream<CourseResult> programmingResults(final Random random) {
    int n = random.nextInt(names.length);
    int l = random.nextInt(lastNames.length);

    return IntStream.iterate(0, i -> i + 1)
            .limit(3)
            .mapToObj(i -> new Person(
                    names[(n + i) % names.length],
                    lastNames[(l + i) % lastNames.length],
                    18 + random.nextInt(20)))
            .map(p -> new CourseResult(p, Arrays.stream(programTasks).collect(toMap(
                    task -> task,
                    task -> random.nextInt(51) + 50))));
}

private Stream<CourseResult> historyResults(final Random random) {
    int n = random.nextInt(names.length);
    int l = random.nextInt(lastNames.length);
    AtomicInteger t = new AtomicInteger(practicalHistoryTasks.length);

    return IntStream.iterate(0, i -> i + 1)
            .limit(3)
            .mapToObj(i -> new Person(
                    names[(n + i) % names.length],
                    lastNames[(l + i) % lastNames.length],
                    18 + random.nextInt(20)))
            .map(p -> new CourseResult(p,
                    IntStream.iterate(t.getAndIncrement(), i -> t.getAndIncrement())
                            .map(i -> i % practicalHistoryTasks.length)
                            .mapToObj(i -> practicalHistoryTasks[i])
                            .limit(3)
                            .collect(toMap(
                                    task -> task,
                                    task -> random.nextInt(51) + 50))));
}

基于这些方法,我可以通过将该任务的分数之和除以3来计算每个任务的平均值,因为只有3个人可以让它除以一个等于流中CourseResult对象数量的数字,如果这些方法改变了它们的. limited(3)。我不知道如何访问任务结果地图的键。我想我需要他们然后返回一个唯一键的地图。每个唯一键的值应该是来自任务结果地图分配给这些键的值的平均值。

共有2个答案

欧阳狐若
2023-03-14

对于您的第一个问题:将每个CourseResult映射到task结果,平面映射以获取每个task结果映射形成所有CourseResults的所有条目,按映射键(任务名称)分组并收集相同键的平均值:

public Map<String, Double> averageScoresPerTask(Stream<CourseResult> results) {
    return results.map(CourseResult::getTaskResults)
            .flatMap(m -> m.entrySet().stream())
            .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.averagingInt(Map.Entry::getValue)));
}

您可以对第二个问题使用相同的方法来计算每个任务的平均值,并最终在结果地图的条目上流式传输以找到平均值最高的任务。

public String easiestTask(Stream<CourseResult> results) {
    return results.map(CourseResult::getTaskResults)
            .flatMap(m -> m.entrySet().stream())
            .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.averagingInt(Map.Entry::getValue)))
            .entrySet().stream()
            .max(Map.Entry.comparingByValue())
            .map(Map.Entry::getKey)
            .orElse("No easy task found");
}

为了避免代码重复,可以在第二个方法中调用第一个方法:

public String easiestTask(Stream<CourseResult> results) {
    return averageScoresPerTask(results).entrySet()
            .stream()
            .max(Map.Entry.comparingByValue())
            .map(Map.Entry::getKey)
            .orElse("No easy task found");
}
诸葛砚文
2023-03-14

要为每个任务创建一个包含平均分数的映射,您需要展平流中每个CourseResult结果对象的maptaskResult,并按键(即任务名称)对数据进行分组。

为此,您可以使用收集器groupingBy(),作为其下游收集器,负责计算映射到同一任务的分数值的平均值,您可以使用averagingDouble()。

这就是它看起来的样子:

public Map<String, Double> averageScoresPerTask(Stream<CourseResult> results) {
    
    return results
        .map(CourseResult::getTaskResults)
        .flatMap(map -> map.entrySet().stream())
        .collect(Collectors.groupingBy(
            Map.Entry::getKey,
            Collectors.averagingDouble(Map.Entry::getValue)
        ));
}

要找到最简单的任务,您可以使用此映射而不是将流作为参数传递。

public String easiestTask( Map<String, Double>  averageByTask) {
    
    return averageByTask.entrySet().stream()
        .max(Map.Entry.comparingByValue())
        .map(Map.Entry::getKey)
        .orElse("no data"); // or orElseThrow() depending on your needs
}
 类似资料:
  • 这是我的代码,它根据一个人所做测试的平均分数返回一个分数。 以下是CourseResult类供参考 和2种生成测试分数的方法。历史结果 和编程结果 所以每个人有3个测试分数。如果我使用编程生成分数,结果很好,因为只有3个编程测试,但是如果我使用历史生成分数,结果我也每个人得到3个测试分数,但是我应该把它当作第四个测试根本没有尝试,这意味着0分。我如何让我的定义标记方法得到收集的测试分数的平均值,而

  • 我试图做以下java分配和每件事似乎工作正常,除了当我把一个数字 谢谢 赋值:创建一个询问考试结果并计算成绩平均值的程序。成绩是4到10之间的浮点数。程序要求成绩,直到键入负数。如果用户给出的分数不是4到10之间的数字,则文本“无效成绩!”将在屏幕上打印,程序要求另一个分数。最后,程序在屏幕上打印输入的成绩数及其平均值,如示例打印所示。如果没有输入成绩,通知“您没有输入任何成绩。”是屏幕上唯一打印

  • 问题内容: 编写一个称为平均值的类,该类可用于计算多个整数的平均值。它应包含以下方法: 接受两个整数参数并返回其平均值的方法。 接受三个整数参数并返回其平均值的方法。 接受两个表示范围的整数参数的方法。 发出错误消息,如果第二个参数小于第一个参数,则返回零。否则,该方法应返回该范围内(含)的整数平均值。实现该类并编写程序以测试其方法并提交源代码(.java文件)。 我被困在第三部分,我什至不真正理

  • 是否可以对流进行求和、平均并将其转换为新对象。我有个目标 现在我想得到这个对象列表的平均值和总和(代码总和价格和代码平均价格) 然后我想创建一个新对象(页脚 这就是我现在所拥有的,它可以工作,但是我要通过两次流。我想要一个方法,我可以通过一次流来做到这一点。 有没有更好的方法做到这一点而不必重复这一点。谢谢

  • 问题内容: 编辑:我已经写了平均的代码,但我不知道如何使它也使用从我的args.length而不是数组的整数 我需要编写一个Java程序,该程序可以计算:1.读入的整数数2.平均值-不必是整数! 注意!我不想从数组中计算平均值,但是要在args中计算整数。 目前我已经写了这个: 谁能指导我正确的方向?还是举个例子,以书面形式指导我塑造这段代码? 提前致谢 问题答案: 只需对您的代码进行一些小的修改

  • 取一定时间内的平均值 用法 Your browser does not support the video tag. 案例:数据变化趋势 功能:加入平均值和不加平均值的折线图形成对比,显示数字改变的规律 工作原理 结果将会是一段时间段输入的平均值。你可以设置配置项中的时间段长度(工程师叫它采样窗) 提示 短的采样窗意为着输出对输入变化的反应更敏感。