Java使用stream进行分组汇总失效问题
背景
在当前项目的开发任务中需要定制财务报表导出功能,格式比较特殊使用了VM。在汇总数据的过程中使用了stream.collect 进行分组汇总。在测试的过程中发现分组失败,最终原因是对象的对比方式问题,collect是根据对象对比的所以需要重写equals。
问题代码
private List<SettlementSheet> sumStkPosition(List<SettlementSheet> dataList){
List<SettlementSheet> resList = new ArrayList<>();
Map<KeyGroup, List<SettlementSheet>> groupedData = dataList.stream()
.collect(Collectors.groupingBy(obj -> new KeyGroup(
obj.getSEATID_(),
obj.getPZ_(),
obj.getHOLDERACC_(),
obj.getSTKCODE_(),
obj.getHEDGINGFLAG_())));
for (Map.Entry<KeyGroup, List<SettlementSheet>> entry : groupedData.entrySet()) {
KeyGroup key = entry.getKey();
List<SettlementSheet> group = entry.getValue();
double sumBstkamt = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getBSTKAMT_().toString()))
.sum();
double sumBcap = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getBSTKAMT_().toString()) *
Double.parseDouble(obj.getBCJJJ_().toString()))
.sum();
double avgBcjjj = sumBstkamt == 0 ? 0 : sumBcap / sumBstkamt;
double sumSstkamt = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getSSTKAMT_().toString()))
.sum();
double sumScap = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getSSTKAMT_().toString()) *
Double.parseDouble(obj.getSCJJJ_().toString()))
.sum();
double avgScjjj = sumSstkamt == 0 ? 0 : sumScap / sumSstkamt;
double dzrjs = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getZRJS_()==null?"0":obj.getZRJS_().toString()))
.max()
.orElse(0.0);
double djrjs = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getJRJS_()==null?"0":obj.getJRJS_().toString()))
.max()
.orElse(0.0);
double ddprofit = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getDPROFIT_().toString()))
.sum();
double dmargin = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getMARGIN_().toString()))
.sum();
double dstkvalueOptd = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getSTKVALUEOPTD_().toString()))
.sum();
double dstkvalueOptk = group.stream()
.mapToDouble(obj -> Double.parseDouble(obj.getSTKVALUEOPTK_().toString()))
.sum();
SettlementSheet rowData = new SettlementSheet();
rowData.setSEATID_(key.getSEATID_());
rowData.setPZ_(key.getPREFIX_());
rowData.setHOLDERACC_(key.getHOLDERACC_());
rowData.setSTKCODE_(key.getSTKCODE_());
rowData.setHEDGINGFLAG_(key.getHEDGINGFLAG_());
rowData.setBSTKAMT_(BigDecimal.valueOf(sumBstkamt));
rowData.setBCJJJ_(BigDecimal.valueOf(avgBcjjj).setScale(2, RoundingMode.HALF_UP));
rowData.setSSTKAMT_(BigDecimal.valueOf(sumSstkamt));
rowData.setSCJJJ_(BigDecimal.valueOf(avgScjjj).setScale(2, RoundingMode.HALF_UP));
rowData.setZRJS_(BigDecimal.valueOf(dzrjs));
rowData.setJRJS_(BigDecimal.valueOf(djrjs));
rowData.setDPROFIT_(BigDecimal.valueOf(ddprofit));
rowData.setMARGIN_(BigDecimal.valueOf(dmargin).setScale(2, RoundingMode.HALF_UP));
rowData.setSTKVALUEOPTD_(BigDecimal.valueOf(dstkvalueOptd));
rowData.setSTKVALUEOPTK_(BigDecimal.valueOf(dstkvalueOptk));
resList.add(rowData);
}
return resList;
}
private class KeyGroup{
private String SEATID_;
public KeyGroup(String SEATID_, String PREFIX_, String HOLDERACC_, String STKCODE_, String HEDGINGFLAG_) {
this.SEATID_ = SEATID_;
this.PREFIX_ = PREFIX_;
this.HOLDERACC_ = HOLDERACC_;
this.STKCODE_ = STKCODE_;
this.HEDGINGFLAG_ = HEDGINGFLAG_;
}
private String PREFIX_;
private String HOLDERACC_;
private String STKCODE_;
private String HEDGINGFLAG_;
public String getSEATID_() {
return SEATID_;
}
public void setSEATID_(String SEATID_) {
this.SEATID_ = SEATID_;
}
public String getPREFIX_() {
return PREFIX_;
}
public void setPREFIX_(String PREFIX_) {
this.PREFIX_ = PREFIX_;
}
public String getHOLDERACC_() {
return HOLDERACC_;
}
public void setHOLDERACC_(String HOLDERACC_) {
this.HOLDERACC_ = HOLDERACC_;
}
public String getSTKCODE_() {
return STKCODE_;
}
public void setSTKCODE_(String STKCODE_) {
this.STKCODE_ = STKCODE_;
}
public String getHEDGINGFLAG_() {
return HEDGINGFLAG_;
}
public void setHEDGINGFLAG_(String HEDGINGFLAG_) {
this.HEDGINGFLAG_ = HEDGINGFLAG_;
}
}
解决方法
重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
KeyGroup mkPriceKey = (KeyGroup) obj;
return Objects.equals(this.SEATID_, mkPriceKey.SEATID_) &&
Objects.equals(this.PREFIX_, mkPriceKey.PREFIX_) &&
Objects.equals(this.HOLDERACC_, mkPriceKey.HOLDERACC_) &&
Objects.equals(this.STKCODE_, mkPriceKey.STKCODE_) &&
Objects.equals(this.HEDGINGFLAG_, mkPriceKey.HEDGINGFLAG_);
}
修正后代码
private class KeyGroup{
private String SEATID_;
public KeyGroup(String SEATID_, String PREFIX_, String HOLDERACC_, String STKCODE_, String HEDGINGFLAG_) {
this.SEATID_ = SEATID_;
this.PREFIX_ = PREFIX_;
this.HOLDERACC_ = HOLDERACC_;
this.STKCODE_ = STKCODE_;
this.HEDGINGFLAG_ = HEDGINGFLAG_;
}
private String PREFIX_;
private String HOLDERACC_;
private String STKCODE_;
private String HEDGINGFLAG_;
public String getSEATID_() {
return SEATID_;
}
public void setSEATID_(String SEATID_) {
this.SEATID_ = SEATID_;
}
public String getPREFIX_() {
return PREFIX_;
}
public void setPREFIX_(String PREFIX_) {
this.PREFIX_ = PREFIX_;
}
public String getHOLDERACC_() {
return HOLDERACC_;
}
public void setHOLDERACC_(String HOLDERACC_) {
this.HOLDERACC_ = HOLDERACC_;
}
public String getSTKCODE_() {
return STKCODE_;
}
public void setSTKCODE_(String STKCODE_) {
this.STKCODE_ = STKCODE_;
}
public String getHEDGINGFLAG_() {
return HEDGINGFLAG_;
}
public void setHEDGINGFLAG_(String HEDGINGFLAG_) {
this.HEDGINGFLAG_ = HEDGINGFLAG_;
}
@Override
public int hashCode() {
return Objects.hash(SEATID_, PREFIX_, HOLDERACC_, STKCODE_, HEDGINGFLAG_);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
KeyGroup mkPriceKey = (KeyGroup) obj;
return Objects.equals(this.SEATID_, mkPriceKey.SEATID_) &&
Objects.equals(this.PREFIX_, mkPriceKey.PREFIX_) &&
Objects.equals(this.HOLDERACC_, mkPriceKey.HOLDERACC_) &&
Objects.equals(this.STKCODE_, mkPriceKey.STKCODE_) &&
Objects.equals(this.HEDGINGFLAG_, mkPriceKey.HEDGINGFLAG_);
}
}
总结
应该有更好的实现方式,java使用的不是很熟练。之后有新思路再来更新。