2015-08-06 12 views
5

mam obiektu:Java 8 Zbierz dwa Listy do mapy przez stan

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

gdzie CurrencyName jest jednym z: EUR, USD, RUR itp

I dwie listy

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

Jak scalić te listy z Map<CurrencyItem, CurrencyItem>, gdzie klucze są currenciesByCommercialBank, a wartościami są currenciesByCentralBank w stanie takim jak

currenciesByCommercialBank.CurrencyName == currenciesByCentralBank.CurrencyName 

Odpowiedz

5

To powinno być optymalne. Najpierw tworzysz mapę z walut do swoich banków komercyjnych. Następnie przechodzisz przez centrale, budując mapę od komercyjnej do centralnej (na pierwszej mapie).

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

Poniższy kod jest O (n), ale powinno być OK dla małych zbiorów (co wasze listy zapewne są):

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)); 
    } 

Powyższe jest właściwe, jeśli chcesz dochodzić to currenciesByCentralBank zawiera dopasowanie dla każdej pozycji w currenciesByCommercialBank. Jeżeli obie listy mogą mieć niedopasowania, a następnie dodaje byłoby właściwe:

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)); 

W tym przypadku map będzie zawierał wszystkie mecze i nie będzie narzekać brakujących wpisów.