поле суммы java 8 от списка объекта с общими множественными полями - PullRequest
0 голосов
/ 05 марта 2019

У меня есть этот список объектов

List<DetailDto> details;
    @Value
    public class DetailDto implements Serializable {
        String category1;
        Integer category2;
        Integer price;

        transient Integer totalPrice;
    }

с этим списком

[
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": null
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": null
  },
  {
    "category1": "GHI",
    "category2": 1,
    "price": 18000,
    "totalPrice": null
  }
]

Я хочу создать еще один List<DetailDto> объект, суммируя поле priceв totalPrice поле, где условия:

  • Строка category1 общие
  • Целые числа category2 общие
  • Целые числа price общие

на данный момент у меня есть это

List<List<DetailDto>> summarizedList = detail().stream()
        .collect(Collectors.groupingBy(DetailDto::category1,
                                       Collectors.groupingBy(DetailDto::category2,
                                                             Collectors.groupingBy(DetailDto::price))))
        .values()
        .stream()
        .flatMap(c1 -> c1.values().stream())
        .flatMap(c2 -> c2.values().stream())
        .collect(Collectors.toList());

, которое возвращает меня List<List<DetailDto>>

, и я не знаю, как сделать это правильно 、 после того, как я попробую это

summarizedList.stream().map(dto -> dto.stream().reduce((x,y) -> new DetailDto(x.productCode(), x.productQt(), x.orderPrice(), Integer.sum(x.orderPrice(), y.orderPrice()).orElse(null).collect(Collectors.toList());

он вернется

[
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": 390
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": 780
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": 910
  },
  {
    "category1": "GHI",
    "category2": 1,
    "price": 18000,
    "totalPrice": null
  }
]

где Что мне действительно нужно, это

[
  {
    "category1": "ABC",
    "category2": 30,
    "price": 195,
    "totalPrice": 585
  },
  {
    "category1": "ABC",
    "category2": 30,
    "price": 390,
    "totalPrice": 780
  },
  {
    "category1": "DEF",
    "category2": 30,
    "price": 455,
    "totalPrice": 1820
  },
  {
    "category1": "GHI",
    "category2": 1,
    "price": 18000,
    "totalPrice": 18000
  }
]

Можете ли вы помочь мне, ребята?

1 Ответ

0 голосов
/ 05 марта 2019

Вот возможность: использовать составной ключ для группировки сразу:

.collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)))

См. Определение Key в DetailDto.java (и обратите внимание на его затмение, сгенерированное hashCode и equals методами.):

import java.io.Serializable;

@SuppressWarnings("serial")
public class DetailDto implements Serializable {
    String category1;
    Integer category2;
    Integer price;

    transient Integer totalPrice;

    public DetailDto() {
    }



    public DetailDto(String category1, Integer category2, Integer price, Integer totalPrice) {
        super();
        this.category1 = category1;
        this.category2 = category2;
        this.price = price;
        this.totalPrice = totalPrice;
    }



    public String getCategory1() {
        return category1;
    }

    public void setCategory1(String category1) {
        this.category1 = category1;
    }

    public Integer getCategory2() {
        return category2;
    }

    public void setCategory2(Integer category2) {
        this.category2 = category2;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public Integer getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(Integer totalPrice) {
        this.totalPrice = totalPrice;
    }

    Key key() {
        return new Key(category1, category2, price);
    }

}
class Key {
    String category1;
    Integer category2;
    Integer price;

    public Key(String category1, Integer category2, Integer price) {
        super();
        this.category1 = category1;
        this.category2 = category2;
        this.price = price;
    }
    public String getCategory1() {
        return category1;
    }
    public Integer getCategory2() {
        return category2;
    }
    public Integer getPrice() {
        return price;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((category1 == null) ? 0 : category1.hashCode());
        result = prime * result + ((category2 == null) ? 0 : category2.hashCode());
        result = prime * result + ((price == null) ? 0 : price.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Key other = (Key) obj;
        if (category1 == null) {
            if (other.category1 != null)
                return false;
        } else if (!category1.equals(other.category1))
            return false;
        if (category2 == null) {
            if (other.category2 != null)
                return false;
        } else if (!category2.equals(other.category2))
            return false;
        if (price == null) {
            if (other.price != null)
                return false;
        } else if (!price.equals(other.price))
            return false;
        return true;
    }
}

Main.java

import java.io.IOException;
import java.util.IntSummaryStatistics;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;

public class Main {

    public static void main(String[] args) throws IOException {
        DetailDto[] values = new ObjectMapper().readerFor(DetailDto[].class)
                .readValue(Main.class.getResourceAsStream("data.json"));
//      for (DetailDto dto : values) {
//          display(dto);
//      }

        Map<Key, IntSummaryStatistics> res = Stream.of(values)
                .collect(Collectors.groupingBy(DetailDto::key, Collectors.summarizingInt(DetailDto::getPrice)));

        Stream<DetailDto> agg = res.entrySet().stream().map(e -> new DetailDto(e.getKey().category1,
                e.getKey().category2, e.getKey().price, (int) e.getValue().getSum()));

        agg.forEach(Main::display);

    }

    protected static void display(DetailDto dto) {
        final ObjectWriter json = new ObjectMapper().writerFor(DetailDto.class).withDefaultPrettyPrinter();
        try {
            System.out.println(json.writeValueAsString(dto));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}

HTH!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...