分组并聚合 Map<String, Object> 列表。

huangapple go评论79阅读模式
英文:

Group and Aggregate List of Map<String, Object>

问题

我有一个类似下面的 List<Map<String, Object>> 输入:

[{
    CURRENCY = USD,
    STATUS = NEW,
    PUBLISH_REGION = DEL,
    SOURCE = ALADDIN,
    RECON_STATUS = null,
    JOB_ID_COUNT = 783
}, {
    CURRENCY = USD,
    STATUS = IN_PROGRESS,
    PUBLISH_REGION = DEL,
    SOURCE = ALADDIN,
    RECON_STATUS = null,
    JOB_ID_COUNT = 462
}, {
    CURRENCY = USD,
    STATUS = NEW,
    PUBLISH_REGION = DEL,
    SOURCE = GROUP,
    RECON_STATUS = null,
    JOB_ID_COUNT = 4
}]

我试图创建另一个 List<Map<String, Object>>,通过在 CURRENCY、PUBLISH_REGION、SOURCE 和 RECON_STATUS 列上进行分组。并将所有唯一的 STATUS 值作为输出映射的透视,并使用 JOB_ID_COUNT 进行汇总/聚合计数。

List<String> groups = new ArrayList<>(asList("SOURCE", "RECON_STATUS", "PUBLISH_REGION", "CURRENCY"));
List<Map<String, Object>> output = input.stream()
    .collect(groupingBy(row -> row.get(groups.get(0)), mapping(map -> map.get(groups.get(0)), toList())));

我期望以下响应:
输出:

[{
        CURRENCY = USD,
        PUBLISH_REGION = DEL,
        SOURCE = ALADDIN,
        RECON_STATUS = null,
        NEW = 783,
        IN_PROGRESS = 462
    }, {
        CURRENCY = USD,
        PUBLISH_REGION = DEL,
        SOURCE = GROUP,
        RECON_STATUS = null,
        NEW = 4,
        IN_PROGRESS = 0
    }]

当我尝试按多个映射字段进行分组时,我遇到编译时错误。单个字段的 groupingBy 正常工作。非常感谢任何帮助。

英文:

I have a List<Map<String, Object>> input like below:

[{
    CURRENCY = USD,
    STATUS = NEW,
    PUBLISH_REGION = DEL,
    SOURCE = ALADDIN,
    RECON_STATUS = null,
    JOB_ID_COUNT = 783
}, {
    CURRENCY = USD,
    STATUS = IN_PROGRESS,
    PUBLISH_REGION = DEL,
    SOURCE = ALADDIN,
    RECON_STATUS = null,
    JOB_ID_COUNT = 462
}, {
    CURRENCY = USD,
    STATUS = NEW,
    PUBLISH_REGION = DEL,
    SOURCE = GROUP,
    RECON_STATUS = null,
    JOB_ID_COUNT = 4
}]

I am trying to create another List<Map<String, Object>> by grouping on CURRENCY, PUBLISH_REGION, SOURCE and RECON_STATUS columns. And add all unique STATUS values as pivot to the output map and use JOB_ID_COUNT to summarize/aggregate the count.

List&lt;String&gt; groups = new ArrayList&lt;&gt;(asList(&quot;SOURCE&quot;, &quot;RECON_STATUS&quot;, &quot;PUBLISH_REGION&quot;, &quot;CURRENCY&quot;));
List&lt;Map&lt;String, Object&gt;&gt; = input.stream()
    .collect(groupingBy(row -&gt; row.get(groups.get(0)), mapping(map -&gt; map.get(groups.get(0)), toList())));

I am expecting below response:
Output:

 [{
        CURRENCY = USD,
        PUBLISH_REGION = DEL,
        SOURCE = ALADDIN,
        RECON_STATUS = null,
        NEW = 783,
        IN_PROGRESS = 462
    }, {
        CURRENCY = USD,
        PUBLISH_REGION = DEL,
        SOURCE = GROUP,
        RECON_STATUS = null,
        NEW = 4,
        IN_PROGRESS = 0
    }]

I am getting compile time error when trying to group by multiple map fields. Single field groupingBy is working fine. Any help is greatly appriciated.

答案1

得分: 1

以下是翻译好的代码部分:

public class MultipleFieldSorting {
    private static Map<String, Object> map, map1, map2;
    private static List<Map<String, Object>> lst = new ArrayList<>();
    static {
        map = new HashMap<>();
        map.put("CURRENCY", "USD");
        map.put("STATUS", "NEW");
        map.put("PUBLISH_REGION", "DEL");
        map.put("SOURCE", "ALADDIN");
        map.put("RECON_STATUS", null);
        map.put("JOB_ID_COUNT", "783");

        map1 = new HashMap<>();
        map1.put("CURRENCY", "USD");
        map1.put("STATUS", "IN_PROGRESS");
        map1.put("PUBLISH_REGION", "DEL");
        map1.put("SOURCE", "ALADDIN");
        map1.put("RECON_STATUS", null);
        map1.put("JOB_ID_COUNT", "462");

        map2 = new HashMap<>();
        map2.put("CURRENCY", "USD");
        map2.put("STATUS", "NEW");
        map2.put("PUBLISH_REGION", "DEL");
        map2.put("SOURCE", "GROUP");
        map2.put("RECON_STATUS", null);
        map2.put("JOB_ID_COUNT", "4");

        lst.add(map);
        lst.add(map1);
        lst.add(map2);
    }

    public static void main(String[] args) {
        List<Map<String, Object>> value = lst.stream()
                .map(map -> new MapWrapper(map))
                .collect(groupingBy(MapWrapper::groupByKey))
                .entrySet()
                .stream()
                .map(e -> e.getValue())
                .map(MapWrapper::map)
                .collect(toList());

        System.out.println(value);
    }
}

class MapWrapper {
    private String currency;
    private String status;
    private String publish;
    private String source;
    private String recon_status;
    private String job_id;

    public MapWrapper(Map<String, Object> map) {
        this.currency = (String) map.get("CURRENCY");
        this.status = (String) map.get("STATUS");
        this.publish = (String) map.get("PUBLISH_REGION");
        this.source = (String) map.get("SOURCE");
        this.recon_status = (String) map.get("RECON_STATUS");
        this.job_id = (String) map.get("JOB_ID_COUNT");
    }

    String groupByKey() {
        return new StringBuilder().append(this.getCurrency()).append("-").append(this.publish)
                .append("-").append(this.source).append("-").append(this.recon_status).toString();
    }

    public static Map<String, Object> map(List<MapWrapper> lst) {
        Map<String, Object> res = new HashMap<>();
        res.put("CURRENCY", lst.get(0).getCurrency());
        res.put("PUBLISH_REGION", lst.get(0).getPublish());
        res.put("SOURCE", lst.get(0).getSource());
        res.put("RECON_STATUS", lst.get(0).getRecon_status());
        for (MapWrapper m : lst) {
            res.put(m.getStatus(), m.getJob_id());
        }
        if (res.get("NEW") == null) {
            res.put("NEW", 0);
        }
        if (res.get("IN_PROGRESS") == null) {
            res.put("IN_PROGRESS", 0);
        }
        return res;
    }

    String getCurrency() {
        return currency;
    }

    void setCurrency(String currency) {
        this.currency = currency;
    }

    String getStatus() {
        return status;
    }

    void setStatus(String status) {
        this.status = status;
    }

    String getPublish() {
        return publish;
    }

    void setPublish(String publish) {
        this.publish = publish;
    }

    String getSource() {
        return source;
    }

    void setSource(String source) {
        this.source = source;
    }

    String getJob_id() {
        return job_id;
    }

    void setJob_id(String job_id) {
        this.job_id = job_id;
    }

    String getRecon_status() {
        return recon_status;
    }

    void setRecon_status(String recon_status) {
        this.recon_status = recon_status;
    }
}
英文:

Tried this solution and it is working

  1. Stream the source List
  2. Map each value of map in the list to Class MapWrapper(a pojo where each key is a field)
  3. GroupBy using the groupByKey defined in MapWrapper(uses CURRENCY, PUBLISH_REGION, SOURCE and RECON_STATUS columns)
    3.a The result is a Map&lt;String, List&lt;MapWrapper&gt;&gt;
    4.Stream through the entry set
  4. map - and get the value alone from (Map&lt;String, List&lt;MapWrapper&gt;&gt;)
  5. Map - convert from List&lt;MapWrapper&gt; to Map&lt;String, Object&gt; using MapWrapper::map
  6. Collect to a list

In Short the solution is

List&lt;Map&lt;String, Object&gt;&gt; value = lst.stream()
.map(map -&gt; new MapWrapper(map))
.collect(groupingBy(MapWrapper::groupByKey))
.entrySet()
.stream()
.map(e -&gt; e.getValue())
.map(MapWrapper::map).collect(toList());

Working Code

public class MultipleFieldSorting {
private static Map&lt;String, Object&gt; map, map1, map2;
private static List&lt;Map&lt;String, Object&gt;&gt; lst = new ArrayList&lt;&gt;();
static {
map = new HashMap&lt;&gt;();
map.put(&quot;CURRENCY&quot;, &quot;USD&quot;);
map.put(&quot;STATUS&quot;, &quot;NEW&quot;);
map.put(&quot;PUBLISH_REGION&quot;, &quot;DEL&quot;);
map.put(&quot;SOURCE&quot;, &quot;ALADDIN&quot;);
map.put(&quot;RECON_STATUS&quot;, null);
map.put(&quot;JOB_ID_COUNT&quot;, &quot;783&quot;);
map1 = new HashMap&lt;&gt;();
map1.put(&quot;CURRENCY&quot;, &quot;USD&quot;);
map1.put(&quot;STATUS&quot;, &quot;IN_PROGRESS&quot;);
map1.put(&quot;PUBLISH_REGION&quot;, &quot;DEL&quot;);
map1.put(&quot;SOURCE&quot;, &quot;ALADDIN&quot;);
map1.put(&quot;RECON_STATUS&quot;, null);
map1.put(&quot;JOB_ID_COUNT&quot;, &quot;462&quot;);
map2 = new HashMap&lt;&gt;();
map2.put(&quot;CURRENCY&quot;, &quot;USD&quot;);
map2.put(&quot;STATUS&quot;, &quot;NEW&quot;);
map2.put(&quot;PUBLISH_REGION&quot;, &quot;DEL&quot;);
map2.put(&quot;SOURCE&quot;, &quot;GROUP&quot;);
map2.put(&quot;RECON_STATUS&quot;, null);
map2.put(&quot;JOB_ID_COUNT&quot;, &quot;4&quot;);
lst.add(map);
lst.add(map1);
lst.add(map2);
}
public static void main(String[] args) {
List&lt;Map&lt;String, Object&gt;&gt; value = lst.stream()
.map(map -&gt; new MapWrapper(map))
.collect(groupingBy(MapWrapper::groupByKey))
.entrySet()
.stream()
.map(e -&gt; e.getValue())
.map(MapWrapper::map).collect(toList());
System.out.println(value);
}
}
class MapWrapper {
private String currency;
private String status;
private String publish;
private String source;
private String recon_status;
private String job_id;
public MapWrapper(Map&lt;String, Object&gt; map) {
this.currency = (String) map.get(&quot;CURRENCY&quot;);
this.status = (String) map.get(&quot;STATUS&quot;);
this.publish = (String) map.get(&quot;PUBLISH_REGION&quot;);
this.source = (String) map.get(&quot;SOURCE&quot;);
this.recon_status = (String) map.get(&quot;RECON_STATUS&quot;);
this.job_id = (String) map.get(&quot;JOB_ID_COUNT&quot;);
}
String groupByKey() {
return new StringBuilder().append(this.getCurrency()).append(&quot;-&quot;).append(this.publish).append(&quot;-&quot;)
.append(this.source).append(&quot;-&quot;).append(this.recon_status).toString();
}
public static Map&lt;String, Object&gt; map(List&lt;MapWrapper&gt; lst){
Map&lt;String, Object&gt; res = new HashMap&lt;&gt;();
res.put(&quot;CURRENCY&quot;,lst.get(0).getCurrency());
res.put(&quot;PUBLISH_REGION&quot;,lst.get(0).getPublish());
res.put(&quot;SOURCE&quot;,lst.get(0).getSource());
res.put(&quot;RECON_STATUS&quot;,lst.get(0).getRecon_status());
for(MapWrapper m : lst){
res.put(m.getStatus(), m.getJob_id());
}
if(res.get(&quot;NEW&quot;)==null){
res.put(&quot;NEW&quot;, 0);
}
if(res.get(&quot;IN_PROGRESS&quot;)==null){
res.put(&quot;IN_PROGRESS&quot;, 0);
}
return res;
}
String getCurrency() {
return currency;
}
void setCurrency(String currency) {
this.currency = currency;
}
String getStatus() {
return status;
}
void setStatus(String status) {
this.status = status;
}
String getPublish() {
return publish;
}
void setPublish(String publish) {
this.publish = publish;
}
String getSource() {
return source;
}
void setSource(String source) {
this.source = source;
}
String getJob_id() {
return job_id;
}
void setJob_id(String job_id) {
this.job_id = job_id;
}
String getRecon_status() {
return recon_status;
}
void setRecon_status(String recon_status) {
this.recon_status = recon_status;
}
}

答案2

得分: 1

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MultipleFieldSorting2 {
    private static Map<String, Object> map, map1, map2;
    private static List<Map<String, Object>> lst = new ArrayList<>();
    static {
        map = new HashMap<>();
        map.put("CURRENCY", "USD");
        map.put("STATUS", "NEW");
        map.put("PUBLISH_REGION", "DEL");
        map.put("SOURCE", "ALADDIN");
        map.put("RECON_STATUS", null);
        map.put("JOB_ID_COUNT", "783");

        map1 = new HashMap<>();
        map1.put("CURRENCY", "USD");
        map1.put("STATUS", "IN_PROGRESS");
        map1.put("PUBLISH_REGION", "DEL");
        map1.put("SOURCE", "ALADDIN");
        map1.put("RECON_STATUS", null);
        map1.put("JOB_ID_COUNT", "462");

        map2 = new HashMap<>();
        map2.put("CURRENCY", "USD");
        map2.put("STATUS", "NEW");
        map2.put("PUBLISH_REGION", "DEL");
        map2.put("SOURCE", "GROUP");
        map2.put("RECON_STATUS", null);
        map2.put("JOB_ID_COUNT", "4");

        lst.add(map);
        lst.add(map1);
        lst.add(map2);
    }

    public static Map<String, Object> mapper(Map<String, Object> e) {

        String key = e.get("CURRENCY") + "-" + e.get("PUBLISH_REGION") + "-" + e.get("SOURCE") + "-" + e.get("RECON_STATUS");
        Map<String, Object> groupedValue = res.get(key);
        if (groupedValue != null) {
            groupedValue.put((String) e.get("STATUS"), groupedValue.get("STATUS") != null ? groupedValue.get("STATUS") + "," + e.get("JOB_ID_COUNT") : e.get("JOB_ID_COUNT"));
            if (groupedValue.get("NEW") == null) {
                groupedValue.put("NEW", 0);
            }
            if (groupedValue.get("IN_PROGRESS") == null) {
                groupedValue.put("IN_PROGRESS", 0);
            }
        } else {
            groupedValue = new HashMap<>();
            res.put(key, groupedValue);
            groupedValue.put("CURRENCY", e.get("CURRENCY"));
            groupedValue.put("PUBLISH_REGION", e.get("PUBLISH_REGION"));
            groupedValue.put("SOURCE", e.get("SOURCE"));
            groupedValue.put("RECON_STATUS", e.get("RECON_STATUS"));
            groupedValue.put((String) e.get("STATUS"), e.get("JOB_ID_COUNT"));
        }
        return groupedValue;

    }

    static Map<String, Map<String, Object>> res = new HashMap<>();

    public static void main(String[] args) {
        List<Map<String, Object>> finalResult = new ArrayList<>();
        lst.stream()
           .map(MultipleFieldSorting2::mapper)
           .forEach(result -> {
               if (!finalResult.contains(result))
                   finalResult.add(result);
           });

        System.out.println(finalResult);
    }
}
英文:

Without Using Custom Class

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MultipleFieldSorting2 {
private static Map&lt;String, Object&gt; map, map1, map2;
private static List&lt;Map&lt;String, Object&gt;&gt; lst = new ArrayList&lt;&gt;();
static {
map = new HashMap&lt;&gt;();
map.put(&quot;CURRENCY&quot;, &quot;USD&quot;);
map.put(&quot;STATUS&quot;, &quot;NEW&quot;);
map.put(&quot;PUBLISH_REGION&quot;, &quot;DEL&quot;);
map.put(&quot;SOURCE&quot;, &quot;ALADDIN&quot;);
map.put(&quot;RECON_STATUS&quot;, null);
map.put(&quot;JOB_ID_COUNT&quot;, &quot;783&quot;);
map1 = new HashMap&lt;&gt;();
map1.put(&quot;CURRENCY&quot;, &quot;USD&quot;);
map1.put(&quot;STATUS&quot;, &quot;IN_PROGRESS&quot;);
map1.put(&quot;PUBLISH_REGION&quot;, &quot;DEL&quot;);
map1.put(&quot;SOURCE&quot;, &quot;ALADDIN&quot;);
map1.put(&quot;RECON_STATUS&quot;, null);
map1.put(&quot;JOB_ID_COUNT&quot;, &quot;462&quot;);
map2 = new HashMap&lt;&gt;();
map2.put(&quot;CURRENCY&quot;, &quot;USD&quot;);
map2.put(&quot;STATUS&quot;, &quot;NEW&quot;);
map2.put(&quot;PUBLISH_REGION&quot;, &quot;DEL&quot;);
map2.put(&quot;SOURCE&quot;, &quot;GROUP&quot;);
map2.put(&quot;RECON_STATUS&quot;, null);
map2.put(&quot;JOB_ID_COUNT&quot;, &quot;4&quot;);
lst.add(map);
lst.add(map1);
lst.add(map2);
}
public static Map&lt;String, Object&gt; mapper(Map&lt;String, Object&gt; e){
String key = e.get(&quot;CURRENCY&quot;) + &quot;-&quot; + e.get(&quot;PUBLISH_REGION&quot;) + &quot;-&quot; + e.get(&quot;SOURCE&quot;) + &quot;-&quot; + e.get(&quot;RECON_STATUS&quot;);
Map&lt;String, Object&gt; groupedValue = res.get(key);
if(groupedValue!=null){
groupedValue.put((String) e.get(&quot;STATUS&quot;), groupedValue.get(&quot;STATUS&quot;)!=null ? groupedValue.get(&quot;STATUS&quot;)+&quot;,&quot;+e.get(&quot;JOB_ID_COUNT&quot;) : e.get(&quot;JOB_ID_COUNT&quot;));
if(groupedValue.get(&quot;NEW&quot;)==null){
groupedValue.put(&quot;NEW&quot;, 0);
}
if(groupedValue.get(&quot;IN_PROGRESS&quot;)==null){
groupedValue.put(&quot;IN_PROGRESS&quot;, 0);
}
}else{
groupedValue = new HashMap&lt;&gt;();
res.put(key, groupedValue);
groupedValue.put(&quot;CURRENCY&quot;, e.get(&quot;CURRENCY&quot;));
groupedValue.put(&quot;PUBLISH_REGION&quot;, e.get(&quot;PUBLISH_REGION&quot;));
groupedValue.put(&quot;SOURCE&quot;, e.get(&quot;SOURCE&quot;));
groupedValue.put(&quot;RECON_STATUS&quot;, e.get(&quot;RECON_STATUS&quot;));
groupedValue.put((String) e.get(&quot;STATUS&quot;), e.get(&quot;JOB_ID_COUNT&quot;));
}
return groupedValue;
}
static Map&lt;String, Map&lt;String, Object&gt;&gt; res = new HashMap&lt;&gt;();
public static void main(String[] args) {
List&lt;Map&lt;String, Object&gt;&gt; finalResult = new ArrayList&lt;&gt;();
lst.stream()
.map(MultipleFieldSorting2::mapper)
.forEach(result -&gt; {
if(!finalResult.contains(result))
finalResult.add(result);
});
System.out.println(finalResult);
}
}

huangapple
  • 本文由 发表于 2020年9月17日 19:36:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/63937199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定