如何在单个流中对对象列表进行分组,计数和求和并存储在另一个对象列表中?

时间:2019-04-21 07:20:57

标签: java collections java-8 java-stream

我试图使用java流和集合从对象列表中获取分组,计数和总和。我不确定如何达到期望的结果。

InputModel

# HTTP - redirect all requests to HTTPS:
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

upstream test_server {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    location / {
        proxy_pass                          http://test_server;
        proxy_http_version                  1.1;
        proxy_set_header  Upgrade           $http_upgrade;
        proxy_set_header  Connection        "upgrade";
        proxy_set_header  Host              $host;
        proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header  X-Real-IP         $remote_addr;
        client_max_body_size                1m;
    }
}

... https block continues ...

InputModel [(May,100,IT,10),(June,300,IT,7),(July,300,IT,7),(May,1000,HR,5),(June,300, HR,7),(July,600,HR,5)]

OutputModel

String month;
BigDecimal salary;
String department;
String noOfEmp;

预期产量 OutputModel [(May,1100,15),(June,600,14),(July,900,12)]

我尝试了下面的代码,但它返回了group by和Count。

String month
BigDecimal salary
String noOfEmp

预先感谢!

2 个答案:

答案 0 :(得分:6)

鉴于您拥有OutputModel类,这将解决您的问题。

Collection<OutputModel> outputModels = inputModel.stream()
    .map(im -> new OutputModel(im.getMonth(), im.getSalary(), im.getNoOfEmp()))
    .collect(Collectors.toMap(OutputModel::getMonth, Function.identity(),
        (m1, m2) -> new OutputModel(m1.getMonth(), m1.getSalary().add(m2.getSalary()),
            String.valueOf(Integer.valueOf(m1.getNoOfEmp()) + Integer.valueOf(m2.getNoOfEmp()))),
        LinkedHashMap::new))
    .values();

警告:最好不要在其他类型更合适的地方使用字符串。例如,您应该使用int代替noOfEmp来代表String。这将简化代码,同时减少由于虚假数据导致的运行时错误的可能性。此外,考虑使用java.time.Month枚举来表示一年中的月份,与使用String文字相反。

这是输出,

  

[{month = May,薪水= 1100,noOfEmp = 15},{month = June,薪水= 600,   noOfEmp = 14},{month =七月,薪水= 900,noOfEmp = 12}]

答案 1 :(得分:3)

您可以结合使用groupingByreducing

Map<String, Optional<OutputModel>> outputModels = inputModel.stream()
            .map(ip -> new OutputModel(ip.getMonth(), ip.getSalary(), ip.getNoOfEmp()))
            .collect(Collectors.groupingBy(OutputModel::getMonth, 
                           LinkedHashMap::new, 
                           Collectors.reducing(OutputModel::merge)));

//the following method goes into OutputModel
public static OutputModel merge(OutputModel o1, OutputModel o2) {
        return new OutputModel(o1.month, o1.salary.add(o1.salary), o1.noOfEmp + o2.noOfEmp);
}

我使用了LinkedHashMap,因此将保留插入顺序,并且我将noOfEmp更改为Integer