【问题标题】:How to replace the indicated values ​of a set with values ​drawn from the list如何用从列表中提取的值替换集合的指示值
【发布时间】:2021-09-05 09:12:56
【问题描述】:

我有一个复杂的obj 对象,其中包含一个CountryUnit 对象,该对象包含countries 的集合。 countries 具有以下 countryValue 值:

countries == {
                Country1 (countryValue == "A")
                Country2 (countryValue == "B")
             }

在这种情况下,我需要进行转换,以便结果集 countries 包含 countryValue 的值,这些值将替换为从 allowedCountryList 中随机选择的值。例如:

countries == {
                Country1 (countryValue == "N")
                Country2 (countryValue == "S")
             }

然后我需要返回 obj 对象,并带有 countryValue 的新值。最简单的方法是什么?我有一段代码,但它不能正常工作。

SomeObject obj; // complex object that contains multiple levels, obj contains CountryUnit object


public class CountryUnit {

      private Set<Country> countries = new HashSet<>();

      // getters, setters
}

public class Country {

        private String countryValue;

        // getters, setters
}

我的代码:

List<String> CountryChecker = Arrays.asList("A", "B", "C");
List<String> allowedCountryList = Arrays.asList("L", "M", "N", "O", "P", "R", "S");

            obj.getSomeSet().stream()
                    .map(CountryUnit::getCountries)
                    .flatMap(Set::stream)
                    .filter((x) -> CountryChecker.contains(x.getCountryValue()))
                    .map(y -> {
                        Random r = new Random();
                        int rCountry = r.nextInt(allowedCountryList.size());
                        y.setCountryValue(allowedCountryList.get(rCountry));
                        return y;
                    });

【问题讨论】:

    标签: java collections stream


    【解决方案1】:

    你快到了。由于您已经在更新现有的 Country 对象,因此请在流上使用 forEach 而不是 map 运算符。

    obj.getSomeSet().stream()
                .map(CountryUnit::getCountries)
                .flatMap(Set::stream)
                .filter((x) -> CountryChecker.contains(x.getCountryValue()))
                .forEach(y -> {
                    Random r = new Random();
                    int rCountry = r.nextInt(allowedCountryList.size());
                    y.setCountryValue(allowedCountryList.get(rCountry));
                });
    

    您可以将 map 和 flatMap 调用组合为:

    obj.getSomeSet().stream()
                .flatMap(countryUnit -> countryUnit.getCountries().stream())
                .filter(country -> CountryChecker.contains(country.getCountryValue()))
                .forEach(country -> {
                    Random r = new Random();
                    int rCountry = r.nextInt(allowedCountryList.size());
                    country.setCountryValue(allowedCountryList.get(rCountry));
                });
    

    如果您遵循 Java 的命名约定,则应将变量名重命名为以小写开头(countryCheckercountriesToUpdate)。如果它是Set 会更好,因为我们在它上面调用contains。使用集合,这将是一个恒定时间操作,而不是线性搜索。

    【讨论】:

    • 为什么将map 更改为forEach 有效?
    • map 是中间操作,而 forEach 是终端操作。在您向其添加终端操作之前,不会调用流管道线。参考:package summary of streamJava streams quick summary
    • 这正是我所需要的。谢谢@user7
    猜你喜欢
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    相关资源
    最近更新 更多