2017-09-27 39 views
1

我有這個類的對象的列表:如何將對象與列表中具有相同值的兩個字段組合爲一個縮小列表?

class Item 
{ 
    private String name; 
    private String parentName; 
    private Integer someValue; 
    private Double anotherValue; 

    public Item() {} 

    //...elided getters/setters... 
} 

我有這些與值的列表:

//PSEUDO CODE (Not JavaScript, but using JSON is easier to follow) 
List<Item> items = [ 
    { 
     "name": "Joe", 
     "parentName": "Frank", 
     "someValue": 10, 
     "anotherValue": 15.0 
    }, 
    { 
     "name": "Joe", 
     "parentName": "Frank", 
     "someValue": 40, 
     "anotherValue": 0.5 
    }, 
    { 
     "name": "Joe", 
     "parentName": "Jack", 
     "someValue": 10, 
     "anotherValue": 10.0 
    }, 
    { 
     "name": "Jeff", 
     "parentName": "Frank", 
     "someValue": 10, 
     "anotherValue": 10.0 
    } 
]; 

我想這是合併到這個列表:

List<Item> items = [ 
    { 
     "name": "Joe", 
     "parentName": "Frank", 
     "someValue": 50, 
     "anotherValue": 15.5 
    }, 
    { 
     "name": "Joe", 
     "parentName": "Jack", 
     "someValue": 10, 
     "anotherValue": 10.0 
    }, 
    { 
     "name": "Jeff", 
     "parentName": "Frank", 
     "someValue": 10, 
     "anotherValue": 10.0 
    } 
]; 

基本上規則是:

  • 如果用戶名和parentName都在兩個對象是相同的:
    • 它們合併成一個對象
    • 琛的「someValue中」場
    • 琛的「anotherValue」字段
  • 如果其中一個name或parentName是diff,不要組合

我該如何在Java 8流中執行此操作?

我開始把它們放入桶(見下文),但我不知道在哪裏何去何從:

items 
    .stream() 
    .collect(
     Collectors.groupingBy(
      item -> new ArrayList<String>(Arrays.asList(item.getName(), item.getParentName())) 
     ) 
    ); 

回答

5

collect(groupingBy())方法返回一個地圖。

如果定義了以下類:

class Tuple { 
    String name; 
    String parentName; 
} 

那麼你就可以得到如下圖:

Map<Tuple, List<Item>> groupedItems = items.stream().collect(
      groupingBy(item -> new Tuple(item.getName(), item.getParentName()))); 

現在你可以對它進行操作是這樣的:

List<Item> finalItems = groupedItems.entrySet().stream().map(entry -> 
       new Item(entry.getKey().name, 
         entry.getKey().parentName, 
         entry.getValue().stream().mapToInt(
            item -> item.someValue).sum(), 
         entry.getValue().stream().mapToDouble(
            item -> item.anotherValue).sum())) 
       .collect(Collectors.toList()); 
1

下面是一個使用一些Java8構建的溶液(雖然它主要通過列表循環,暫時將項目存儲在地圖中)。 :

List<Item> items; 
Map<String, Item> masterItems; 

    items.forEach(item -> { 
     if (masterItems.containsKey(item.getName() + item.getParent())) { 
      Item matchedItem = masterItems.get(item.getName() + item.getParent()); 
      matchedItem.setSomeValue(matchedItem.getSomeValue() + item.getSomeValue()); 
      matchedItem.setOtherValue(matchedItem.getOtherValue() + item.getOtherValue()); 
     } else { 
      masterItems.put(item.getName() + item.getParent(), item); 
     } 
    }); 
    items.clear(); 
    items.addAll(masterItems.values()); 

這也許可以細化到使用更Java8結構......我將有一個去看看我能做些什麼

相關問題