Java Stream API,如何平均排序?

问题描述 投票:0回答:3

问题:

Create a program that keeps information about some students and their grades.

You will receive an integer number - n.

Then, you will receive 2 \* n rows of input.

First, you will receive the student's name. Аfter that, you will receive their grade.

If the student does not exist, add them.

Keep track of all of the grades of each student.

When you finish reading the data, keep only the students which have an average grade higher or equal to 4.50.

Order the filtered students by their average grade in descending order.

Print the students and their average grade in the following format:

"{name} -\> {averageGrade}"

Format the average grade to the second decimal place.

测试输入:

5
John
5.5
John
4.5
Alice
6
Alice
3
George
5

测试输出:

John -> 5.00
George -> 5.00
Alice -> 4.50

我的回答:

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int n = Integer.parseInt(scanner.nextLine());

        Map<String, List<Double>> records = new HashMap<>();

        while(n > 0){
            String name = scanner.nextLine();
            double grade = Double.parseDouble(scanner.nextLine());
            records.putIfAbsent(name, new ArrayList<>());
            records.get(name).add(grade);
            n--;
        }

        records.entrySet().stream().filter(item -> {
            double average = item.getValue().stream().mapToDouble(x -> x).average().getAsDouble();

            return average >= 4.50;
        }).sorted((a, b) -> {
            double average1 = a.getValue().stream().mapToDouble(x -> x).average().getAsDouble();
            double average2 = b.getValue().stream().mapToDouble(x -> x).average().getAsDouble();

            return (int) (average2 - average1);
        }).forEach(pair -> {
            double average = pair.getValue().stream().mapToDouble(x -> x).average().getAsDouble();
            System.out.printf("%s -> %.2f%n", pair.getKey(), average);
        });
    }
}

我很确定我没有正确地按平均部分进行排序,但我似乎无法找到另一种方法来进行排序,因为排序需要一个 int 并且平均值始终是双精度?

任何指示/解释将不胜感激!

java stream average
3个回答
2
投票

输入后,您可以按照以下代码片段操作

我们可以制作一个新的地图,以名称为键,平均值为值,而不是多次计算平均值

 Map<String, Double> recordsWithAverage = records.entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().stream().mapToDouble(x -> x).average().getAsDouble()));

 recordsWithAverage.entrySet()
            .stream()
            .filter(e -> e.getValue() >= 4.50)
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .forEach(pair -> {
                System.out.printf("%s -> %.2f%n", pair.getKey(), pair.getValue());
            });    

2
投票

试试这个。

public static void main(String[] args) throws IOException {
    String input = "5\r\n"
        + "John\r\n"
        + "5.5\r\n"
        + "John\r\n"
        + "4.5\r\n"
        + "Alice\r\n"
        + "6\r\n"
        + "Alice\r\n"
        + "3\r\n"
        + "George\r\n"
        + "5\r\n";
    Scanner in = new Scanner(input);
    int size = in.nextInt();
    Map<String, List<Double>> map = new HashMap<>();
    for (int i = 0; i < size; ++i)
        map.computeIfAbsent(in.next(), k -> new ArrayList<>()).add(in.nextDouble());

    map.entrySet().stream()
        .map(e -> Map.entry(e.getKey(),
            e.getValue().stream().mapToDouble(v -> v).average().getAsDouble()))
        .filter(e -> e.getValue() >= 4.50)
        .sorted(Collections.reverseOrder(Comparator.comparing(Entry::getValue)))
        .forEach(e -> System.out.printf("%s -> %.2f%n", e.getKey(), e.getValue()));
}

输出:

George -> 5.00
John -> 5.00
Alice -> 4.50

0
投票
record AverageGrade(String name, double average) {}
records.entrySet().stream()
        .map(e -> new AverageGrade(e.getKey(),
                e.getValue().stream().mapToDouble(Double::doubleValue)
                        .average().orElseThrow()))
        .filter(g -> g.average() >= 4.5)
        .sorted(Comparator.comparing(AverageGrade::average).reversed())
        .forEachOrdered(g -> System.out.printf("%s -> %.2f%n", g.name(), g.average()));

这会将映射中的每个条目映射到一个简单的

AverageGrade
记录。然后它会对地图进行过滤和排序。它使用
Comparator.comparing
根据
average
属性对条目进行排序,并反转该顺序以使它们按降序排列。

© www.soinside.com 2019 - 2024. All rights reserved.