簡體   English   中英

如何將一個列表中具有相同值的兩個字段的對象合並為一個簡化列表?

[英]How can I combine objects with two fields having the same values in a list into one reduced list?

我有一個此類的對象列表:

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”字段求和
  • 如果名稱或parentName之一是diff,請不要合並

我將如何在Java 8流中做到這一點?

我從將它們放入水桶開始(請參見下文),但不確定從何處去:

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

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

這是一個使用某些Java8構造的解決方案(盡管其本質上是遍歷List的循環,將項臨時存儲在Map中)。

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構造...我去看看我能做什么

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM