gpt4 book ai didi

java - 嵌套列表不适用的 Java 流上的 Limit()

转载 作者:行者123 更新时间:2023-11-29 07:28:43 26 4
gpt4 key购买 nike

我有一个列表 Category ,每个都有一个列表 Phrase s,我想将此列表缩减为具有最少短语数的类别,将短语数限制为 Y,然后创建一个新对象 CategoryAndPhrase对于所有匹配的类别和短语。

这似乎是 Java 8 流 API 的一个很好的候选者,但我没有得到我期望的结果。这是我的代码,每行旁边都有注释,解释了我要实现的目标。此问题末尾有完整的代码示例。

List<CategoryAndPhrase> categoriesAndPhrases = allCategories.stream()
.filter(category -> category.getPhrases().size() >= numberOfPhrasesPerCategory) // remove the categories which don't have enough phrases to match our criteria
.limit(numberOfCategories) // reduce the list to the number categories we require
.map(Category::getPhrases) // change the stream so it is now a stream of the phrases for the selected categories
.limit(numberOfPhrasesPerCategory) // reduce the phrases for each of the selected categories to the number of phrases we require
.flatMap(List::stream)
.map(phrase -> new CategoryAndPhrase(phrase.getCategory(), phrase.getName())) // create the new object for each of the selected phrases
.collect(Collectors.toCollection(ArrayList::new));

例子

输入数据:

  • 运动队 <-- Category
    • 曼联 <-- Phrase
    • 阿森纳
    • 斯旺西
    • 哈特尔浦联队
  • 问候
    • 你好
  • 再见
    • 再见
    • 再见
    • 再见
  • 语言
    • 英语
    • 意大利语
    • 法语
    • 德语

类别数:2

每个类别的短语数:3

预期输出:

  • 类别:[运动队],短语:[Manchester United]
  • 类别:[运动队],短语:[阿森纳]
  • 类别:[运动队],短语:[斯旺西]
  • 类别:[再见],短语:[再见]
  • 类别:[再见],短语:[Adios]
  • 类别:[再见],短语:[Au revoir]

实际输出:

  • 类别:[运动队],短语:[Manchester United]
  • 类别:[运动队],短语:[阿森纳]
  • 类别:[运动队],短语:[斯旺西]
  • 类别:[运动队],短语:[Hartlepool United]
  • 类别:[再见],短语:[再见]
  • 类别:[再见],短语:[Adios]
  • 类别:[再见],短语:[Au revoir]

请注意,尽管我只要求每个类别 3 个短语,但第四个运动队也包括在内。

第一个limit()操作似乎正常工作,因为只有两个类别返回,即使三个类别符合至少三个短语的标准,但第二个类别没有按预期工作。

我哪里错了?

完整代码

您还可以找到此代码 on JDoodle .

import java.util.List;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.LinkedList;
import java.util.ArrayList;

public class MyClass {
public static void main(String args[]) {
new MyClass().run();
}

public void run() {
Phrase sportsTeam1 = new Phrase("Manchester United", "Sports Teams");
Phrase sportsTeam2 = new Phrase("Arsenal", "Sports Teams");
Phrase sportsTeam3 = new Phrase("Swansea", "Sports Teams");
Phrase sportsTeam4 = new Phrase("Hartlepool United", "Sports Teams");
Category sportsTeams = new Category("Sports Teams", Arrays.asList(sportsTeam1, sportsTeam2, sportsTeam3, sportsTeam4));

Phrase greeting1 = new Phrase("Hello", "Greetings");
Category greetings = new Category("Greetings", Arrays.asList(greeting1));

Phrase goodbye1 = new Phrase("Goodbye", "Goodbyes");
Phrase goodbye2 = new Phrase("Adios", "Goodbyes");
Phrase goodbye3 = new Phrase("Au revoir", "Goodbyes");
Category goodbyes = new Category("Goodbyes", Arrays.asList(goodbye1, goodbye2, goodbye3));

Phrase language1 = new Phrase("English", "Languages");
Phrase language2 = new Phrase("Italian", "Languages");
Phrase language3 = new Phrase("French", "Languages");
Phrase language4 = new Phrase("German", "Languages");
Category languages = new Category("Languages", Arrays.asList(language1, language2, language3, language4));

List<Category> allCategories = Arrays.asList(sportsTeams, greetings, goodbyes, languages);
int numberOfCategories = 2;
int numberOfPhrasesPerCategory = 3;

List<CategoryAndPhrase> categoriesAndPhrases = allCategories.stream()
.filter(category -> category.getPhrases().size() >= numberOfPhrasesPerCategory) // remove the categories which don't have enough phrases to match our criteria
.limit(numberOfCategories) // reduce the list to the number categories we require
.map(Category::getPhrases) // change the stream so it is now a stream of the phrases for the selected categories
.limit(numberOfPhrasesPerCategory) // reduce the phrases for each of the selected categories to the number of phrases we require
.flatMap(List::stream)
.map(phrase -> new CategoryAndPhrase(phrase.getCategory(), phrase.getName())) // create the new object for each of the selected phrases
.collect(Collectors.toCollection(ArrayList::new));

categoriesAndPhrases.forEach(categoryAndPhrase -> System.out.println(categoryAndPhrase));
}

class Category {

private final String name;
private final List<Phrase> phrases;

public Category(final String name, final List<Phrase> phrases) {
this.name = name;
this.phrases = phrases;
}

public String toString() {
return name;
}

public String getName() {
return name;
}

public List<Phrase> getPhrases() {
return phrases;
}
}

class Phrase {

private final String name;
private final String category;

public Phrase(final String name, final String category) {
this.name = name;
this.category = category;
}

public String toString() {
return name;
}

public String getName() {
return name;
}

public String getCategory() {
return category;
}
}

class CategoryAndPhrase {

private final String category;
private final String phrase;

public CategoryAndPhrase(final String category, final String phrase) {
this.category = category;
this.phrase = phrase;
}

public String toString() {
return "Category: [" + category + "], Phrase: [" + phrase + "]";
}
}
}

最佳答案

limit() 在看到给定数量的元素后停止处理流元素。

这是您的代码实际执行的操作:

List<CategoryAndPhrase> categoriesAndPhrases = allCategories.stream()
.filter(category -> category.getPhrases().size() >= numberOfPhrasesPerCategory) // remove the categories which don't have enough phrases to match our criteria
.limit(numberOfCategories) // reduce the list to the number categories we require
.map(Category::getPhrases) // transforms the Stream<Category> into a Stream<List<Phrase>>, where each category of the original stream is "replaced" by its list of phrases.
.limit(numberOfPhrasesPerCategory) // only process N lists among all the lists of phrases

你应该做的是:

List<CategoryAndPhrase> categoriesAndPhrases = allCategories.stream()
.filter(category -> category.getPhrases().size() >= numberOfPhrasesPerCategory) // remove the categories which don't have enough phrases to match our criteria
.limit(numberOfCategories) // reduce the list to the number categories we require
.flatMap(category -> this.createCategoryAndPhrases(category, numberOfPhrasesPerCategory))
.collect(Collectors.toList());

createCategoryAndPhrases 方法应该如下所示:

private Stream<CategoryAndPhrase> createCategoryAndPhrases(Category category, int maxNumberOfPhrasesPerCategory) {
return category.getPhrases().stream()
.limit(maxNumberOfPhrasesPerCategory)
.map(phrase -> new CategoryAndPhrase(category, phrase.getName()));
}

关于java - 嵌套列表不适用的 Java 流上的 Limit(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46224931/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com