简体   繁体   English

Java 8:简化代码并将其转换为流 API

[英]Java 8: Simplify and convert code to stream API

Code structure代码结构

public class Article {
   public String name;   
   public String description;
   public List<Translation> translations;
}

public class Translation { 
   public String field;
   public String value;
   public String language;
}

There is a method to transform and return specific result有一种方法可以转换并返回特定结果

List<Article> returnArticleswithCorrectTranslation(List<Article> articles, String language) {
    List<Article> result = new ArrayList<>();
    for (Article article: articles) {
        String languageCriteria = language;
        boolean isTranslationFound = false;
        for (Translation translation : article.translations) {
            if (translation.language.equals(language)) {
              isTranslationFound = true;
            }
        }

        if (!isTranslationFound) {
            languageCriteria = "en";
        }
        List<Translation> resultTranslations = new ArrayList<>();
        for (Translation translation : article.translations) {
            if (translation.language.equals(languageCriteria)) {
                resultTranslations.add(translation);
            }
        }
        article.translations = resultTranslations;
        result.add(article);

    }
    return result;
}

Need an advice how can I convert that logic to Java 8 stream api ?需要建议如何将该逻辑转换为 Java 8 流 api?

Such questions are more suitable for CodeReview , but ok, I'll answer.这样的问题更适合CodeReview ,不过好吧,我来回答。

First, even in previous Java versions there's no need to create the result list in the loop.首先,即使在以前的 Java 版本中,也不需要在循环中创建result列表。 The result is actually the same List as the input articles list as you don't create new objects, you modify the existing ones.result实际上是相同的List作为输入articles列为你不创建新对象,修改现有的。 Thus if you want to copy the original list (for whatever reason), you could write simply:因此,如果您想复制原始列表(无论出于何种原因),您可以简单地编写:

return new ArrayList<>(articles);

But probably you may omit the copying and return simply articles .但可能你可以省略复制并返回简单的articles Or even better change the return type to void .或者甚至更好地将返回类型更改为void This way it will be more clear that your method actually changes the passed objects instead of creating the new ones.通过这种方式,您的方法实际上会更改传递的对象而不是创建新对象,这将更加清晰。

To search whether the Collection has element matching the given predicate use Stream.anyMatch() :要搜索Collection是否具有与给定谓词匹配的元素,请使用Stream.anyMatch()

String languageCriteria = 
        article.translations.stream().anyMatch(t -> t.language.equals(language)) 
        ? language : "en";

To filter the elements according to the given predicate use Stream.filter() :要根据给定的谓词过滤元素,请使用Stream.filter()

article.translations = article.translations.stream()
        .filter(t -> t.language.equals(languageCriteria))
        .collect(Collectors.toList());

Though it's likely that the original article.translations list is not used anywhere alse, and you can perform the filtering in-place using Collection.removeIf() instead of creating the Stream and separate List :尽管原始article.translations列表很可能没有在其他任何地方使用,但您可以使用Collection.removeIf()执行就地过滤,而不是创建Stream和单独的List

article.translations.removeIf(t -> !t.language.equals(languageCriteria));

So your method might look like this:所以你的方法可能是这样的:

void filterArticleTranslations(List<Article> articles, String language) {
    articles.forEach(article -> {
        String languageCriteria = 
                article.translations.stream().anyMatch(t -> t.language.equals(language)) 
                ? language : "en";

        article.translations.removeIf(t -> !t.language.equals(languageCriteria));
    });
}

Further to encapsulate the Article modifications I would extract the loop body to the method of Article class:为了进一步封装Article修改,我将循环体提取到Article类的方法中:

public static class Article {
    String name;
    String description;
    List<Translation> translations;

    public void filterTranslations(String language) {
        String languageCriteria = 
                translations.stream().anyMatch(t -> t.language.equals(language)) 
                ? language : "en";

        translations.removeIf(t -> !t.language.equals(languageCriteria));
    }
}

Now your original method may look like this:现在您的原始方法可能如下所示:

void filterArticleTranslations(List<Article> articles, String language) {
    articles.forEach(article -> article.filterTranslations(language));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM