使用流和收集器创建嵌套地图

发布于 2025-01-22 03:39:08 字数 1704 浏览 0 评论 0原文

class QuizAnswers {
  List<MultipleChoiceAnswer> multipleChoiceAnswers;
  List<FreeResponseAnswer> freeResponseAnswers; //not relevant to this question
}

class MultipleChoiceAnswer {
  int questionId;
  // The index of the selected multiple choice question
  int answer_selection;
}

我功能的输入是list&lt; quizanswers&gt;

我想创建一个map&lt; integer的输出,映射,long&gt;&gt;,映射映射&lt; multiplechoiceanswer.questionId:&lumertipleChoiceAceAnswer.answer_answer_swer_selection代码>。换句话说,我想创建一个嵌套的地图,将每个多项选择测验问题映射到表示该测验问题每个答案选择总数的地图。

假设输入list&lt; quizanswers&gt; quizanswerslist as:

[ {questionId: 1, answer_selection: 2},    
  {questionId: 1, answer_selection:2},  
  {questionId: 1, answer_selection:3},   
  {questionId: 2, answer_selection:1} ]

然后我希望输出为:

{1 : {2:2, 3:1}, 2: {1, 1}}

因为id = 1接收到答案选择的两个选择21 < /code>在答案选择上选择3 id = 2 hate 1选择答案选择1

我已经尝试过,

quizAnswersList.stream()
            .map(
                quizAnswers ->
                    quizAnswers.getMultipleChoiceAnswers().stream()
                        .collect(
                            Collectors.groupingBy(
                                MultipleChoiceAnswer::getQuestionId,
                                Collectors.groupingBy(
                                    MultipleChoiceAnswer::getAnswerSelection,
                                    Collectors.counting()))));

这给了我一个错误。我对流的溪流和收藏家并不熟悉,所以我很想学习如何正确执行此操作。

class QuizAnswers {
  List<MultipleChoiceAnswer> multipleChoiceAnswers;
  List<FreeResponseAnswer> freeResponseAnswers; //not relevant to this question
}

class MultipleChoiceAnswer {
  int questionId;
  // The index of the selected multiple choice question
  int answer_selection;
}

The input to my function is a List<QuizAnswers>.

I want to create an output of Map<Integer, Map<Integer, Long>> that maps <MultipleChoiceAnswer.questionId : <MultipleChoiceAnswer.answer_selection, total count of answer_selection>. In other words, I want to create a nested map that maps each multiple choice quiz question to a map representing the total number of selections on each answer choice of that quiz question.

Suppose the input List<QuizAnswers> quizAnswersList as:

[ {questionId: 1, answer_selection: 2},    
  {questionId: 1, answer_selection:2},  
  {questionId: 1, answer_selection:3},   
  {questionId: 2, answer_selection:1} ]

Then I would want the output to be:

{1 : {2:2, 3:1}, 2: {1, 1}}

Because the question with Id = 1 received two selections on answer choice 2 and 1 selection on answer choice 3 while the question with Id=2 had 1 selection on answer choice 1.

I have tried

quizAnswersList.stream()
            .map(
                quizAnswers ->
                    quizAnswers.getMultipleChoiceAnswers().stream()
                        .collect(
                            Collectors.groupingBy(
                                MultipleChoiceAnswer::getQuestionId,
                                Collectors.groupingBy(
                                    MultipleChoiceAnswer::getAnswerSelection,
                                    Collectors.counting()))));

Which is giving me an error. I am not very familiar with streams and collectors in general, so I'd love to learn how to do this correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟─花易冷 2025-01-29 03:39:08

我想创建一个output map&lt; integer,map&lt; integer,long&gt;&gt;映射映射; multiplechoiceanswer.questionid:questionId:&lt; multipleChoiceCeanswer.answer.answer.answer.answer.answer_selection&gt; gt; gt; gt; gt; ,答案的总数&gt;。

你很近。您只是没有flatmap 多人杂志在流上,因此您有一个嵌套的流,这引起了问题。

根据您编辑的问题,这是我想到的。

List<MultipleChoiceAnswer> mca =
        List.of(new MultipleChoiceAnswer(1, 2),
                new MultipleChoiceAnswer(1, 2),
                new MultipleChoiceAnswer(1, 3),
                new MultipleChoiceAnswer(2, 1));

// more could be added to the List.  You only provided one.
List<QuizAnswers> list = List.of(new QuizAnswers(mca));
  • flatMap all the MultipleChoice lists
  • group them by the questionId
  • then subgroup them according to AnswerSelection and get a count
  • then you get the Map output you requested.
Map<Integer,Map<Integer,Long>> map = list.stream()
        .flatMap(s -> s.getMultipleChoiceAnswers().stream())
        .collect(Collectors.groupingBy(
                MultipleChoiceAnswer::getQuestionId,
                Collectors.groupingBy(
                        MultipleChoiceAnswer::getAnswerSelection,
                        Collectors.counting())));

map.entrySet().forEach(System.out::println);

打印

1={2=2, 3=1}
2={1=1}

问题

  • 您要如何处理多个quizanswer实例?
  • 您要如何处理多个mulitplechoiceanswer列表。您只提供了其中一个。

它们都可以是flatmapped一起处理,并如上所述进行处理。但是我认为答案(也许对于不同的测试)可能会有一些差异,而您不希望将其分组和算作相同。

示例

如果我将以下内容添加到list&lt; quizanswers&gt;

List<MultipleChoiceAnswer> mca2 =
List.of(new MultipleChoiceAnswer(1, 2),
        new MultipleChoiceAnswer(1, 2),
        new MultipleChoiceAnswer(5, 2),
        new MultipleChoiceAnswer(5, 2));

和使用上述解决方案的过程中,则输出将为

1={2=4, 3=1}
2={1=1}
5={2=2}

I want to create an output of Map<Integer, Map<Integer, Long>> that maps <MultipleChoiceAnswer.questionId : <MultipleChoiceAnswer.answer_selection>, total count of answer_selection>.

You were close. You just didn't flatMap the MultipleChoiceAnswers onto the stream so you had a nested stream and that was causing the problem.

Based on your edited question, here is what I came up with.

List<MultipleChoiceAnswer> mca =
        List.of(new MultipleChoiceAnswer(1, 2),
                new MultipleChoiceAnswer(1, 2),
                new MultipleChoiceAnswer(1, 3),
                new MultipleChoiceAnswer(2, 1));

// more could be added to the List.  You only provided one.
List<QuizAnswers> list = List.of(new QuizAnswers(mca));
  • flatMap all the MultipleChoice lists
  • group them by the questionId
  • then subgroup them according to AnswerSelection and get a count
  • then you get the Map output you requested.
Map<Integer,Map<Integer,Long>> map = list.stream()
        .flatMap(s -> s.getMultipleChoiceAnswers().stream())
        .collect(Collectors.groupingBy(
                MultipleChoiceAnswer::getQuestionId,
                Collectors.groupingBy(
                        MultipleChoiceAnswer::getAnswerSelection,
                        Collectors.counting())));

map.entrySet().forEach(System.out::println);

prints

1={2=2, 3=1}
2={1=1}

Questions

  • how do you want to handle multiple QuizAnswer instances?
  • how do you want to handle multiple MulitpleChoiceAnswer lists. You only provided one of each.

They could all be flatmapped together and processed as above. But I think there could be some differences in the Answers (perhaps for different tests) which you don't want grouped and counted as the same.

Example

If I add the following to the List<QuizAnswers>

List<MultipleChoiceAnswer> mca2 =
List.of(new MultipleChoiceAnswer(1, 2),
        new MultipleChoiceAnswer(1, 2),
        new MultipleChoiceAnswer(5, 2),
        new MultipleChoiceAnswer(5, 2));

And process using the above solution, the output would be

1={2=4, 3=1}
2={1=1}
5={2=2}

池木 2025-01-29 03:39:08

输入我的功能是list&lt; quizanswers&gt;。我想创建一个map&lt; integer的输出

我尝试过quizanswerslist.stream()。映射(quizanswers - &gt; ...)
这给了我一个错误。

方法map()是一个中间操作,即它产生a stream 。因此,如果您尝试将 stratement 分配给您已列出的类型map的变量,则会遇到汇编错误。

流管线需要以collect之类的终端操作结束,以便被执行并产生结果。

collect()您必须应用 flatmap() ,期望流>作为一个参数,将quizanswers的流将其转换为多人杂货>的流

您对收集器的使用是正确的,不需要任何更改。

public static void main(String[] args) {
    List<QuizAnswers> quizAnswersList =
        List.of(new QuizAnswers(List.of(new MultipleChoiceAnswer(1, 2),
                                        new MultipleChoiceAnswer(1, 2))),
                new QuizAnswers(List.of(new MultipleChoiceAnswer(1, 3),
                                        new MultipleChoiceAnswer(2, 1))));

    Map<Integer, Map<Integer, Long>> totalCountOfAnswerSelectionByQuestion =
        quizAnswersList.stream()
            .flatMap(quizAnswers -> quizAnswers.getMultipleChoiceAnswers().stream())
            .collect(Collectors.groupingBy(MultipleChoiceAnswer::getQuestionId,
                        Collectors.groupingBy(MultipleChoiceAnswer::getAnswerSelection,
                            Collectors.counting())));

    System.out.println(totalCountOfAnswerSelectionByQuestion);
}

输出

{1={2=2, 3=1}, 2={1=1}}

input to my function is a List<QuizAnswers>. I want to create an output of Map<Integer, Map<Integer, Long>>

I have tried quizAnswersList.stream().map(quizAnswers -> ... )
which is giving me an error.

Method map() is an intermediate operation, i.e. it yields a stream. Therefore, if you try to assign the stream-statement you've listed to a variable of type Map you'll get a compilation error.

A stream pipeline needs to end with a terminal operation like collect in order to be executed and produce a result.

And before collect() you have to apply flatMap(), which expects a stream as an argument, to transform the stream of QuizAnswers in to a stream of MultipleChoiceAnswer.

Your usage of collectors is correct and doesn't require any changes.

public static void main(String[] args) {
    List<QuizAnswers> quizAnswersList =
        List.of(new QuizAnswers(List.of(new MultipleChoiceAnswer(1, 2),
                                        new MultipleChoiceAnswer(1, 2))),
                new QuizAnswers(List.of(new MultipleChoiceAnswer(1, 3),
                                        new MultipleChoiceAnswer(2, 1))));

    Map<Integer, Map<Integer, Long>> totalCountOfAnswerSelectionByQuestion =
        quizAnswersList.stream()
            .flatMap(quizAnswers -> quizAnswers.getMultipleChoiceAnswers().stream())
            .collect(Collectors.groupingBy(MultipleChoiceAnswer::getQuestionId,
                        Collectors.groupingBy(MultipleChoiceAnswer::getAnswerSelection,
                            Collectors.counting())));

    System.out.println(totalCountOfAnswerSelectionByQuestion);
}

Output

{1={2=2, 3=1}, 2={1=1}}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文