【问题标题】:Java 8 Collect two Lists to Map by conditionJava 8 收集两个列表以按条件映射
【发布时间】:2015-08-06 12:10:47
【问题描述】:

我有一个对象:

public class CurrencyItem {
    private CurrencyName name;
    private BigDecimal buy;
    private BigDecimal sale;
    private Date date;
    //...
}

其中CurrencyName 是以下之一:EUR、USD、RUR 等。

还有两个列表

List<CurrencyItem> currenciesByCommercialBank = ...
List<CurrencyItem> currenciesByCentralBank = ...

如何将此列表合并到Map&lt;CurrencyItem, CurrencyItem&gt;,其中键为currenciesByCommercialBank,值为currenciesByCentralBank,条件为

currenciesByCommercialBank.CurrencyName == currenciesByCentralBank.CurrencyName

【问题讨论】:

    标签: java collections java-8 java-stream


    【解决方案1】:

    这应该是最佳的。您首先构建一张从货币到其商业银行的地图。然后你穿过你的中心,构建一张从商业到中心的地图(在第一张地图中查找)。

        List<CurrencyItem> currenciesByCommercialBank = new ArrayList<>();
        List<CurrencyItem> currenciesByCentralBank = new ArrayList<>();
        // Build my lookup from CurrencyName to CommercialBank.
        Map<CurrencyName, CurrencyItem> commercials = currenciesByCommercialBank
                .stream()
                .collect(
                        Collectors.toMap(
                                // Map from currency name.
                                ci -> ci.getName(),
                                // To the commercial bank itself.
                                ci -> ci));
        Map<CurrencyItem, CurrencyItem> commercialToCentral = currenciesByCentralBank
                .stream()
                .collect(
                        Collectors.toMap(
                                // Map from the equivalent commercial
                                ci -> commercials.get(ci.getName()),
                                // To this central.
                                ci -> ci
                        ));
    

    【讨论】:

      【解决方案2】:

      以下代码为 O(n2),但对于小型集合(您的列表可能是)应该没问题:

      return currenciesByCommercialBank
          .stream()
          .map(c ->
              new AbstractMap.SimpleImmutableEntry<>(
                  c, currenciesByCentralBank.stream()
                                            .filter(c2 -> c.currencyName == c2.currencyName)
                                            .findFirst()
                                            .get()))
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        }
      

      如果您想断言currenciesByCentralBank 包含currenciesByCommercialBank 中的每个项目的匹配项,则上述内容是合适的。如果这两个列表可能不匹配,则以下是合适的:

      currenciesByCommercialBank
          .stream()
          .flatMap(c ->
              currenciesByCentralBank.stream()
                                     .filter(c2 -> c.currencyName == c2.currencyName)
                                     .map(c2 -> new AbstractMap.SimpleImmutableEntry<>(c, c2)))
          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
      

      在这种情况下,地图将包含所有匹配项,并且不会抱怨缺少条目。

      【讨论】:

        猜你喜欢
        • 2017-09-22
        • 2019-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多