Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Joins in Java 8 Collection API

I have two List<Map<String, Object>> object.

[{Month=August-2013, Sales=282200}, {Month=July-2013, Sales=310400}, 
 {Month=June-2013, Sales=309600}, {Month=May-2013, Sales=318200}, 
 {Month=September-2013, Sales=257800}]

and

[{Month=April-2013, NoOfTranx=8600}, {Month=August-2013, NoOfTranx=6700}, 
 {Month=July-2013, NoOfTranx=14400}, {Month=June-2013, NoOfTranx=8500}, 
 {Month=May-2013, NoOfTranx=14400}]

I want to join(Merge) these two List on Month key. How can I perform several join operation (i.e. FULL OUTER JOIN, RIGHT OUTER JOIN etc.) on these List using new Collection API.

like image 574
Anurag Tripathi Avatar asked May 09 '14 11:05

Anurag Tripathi


People also ask

How do you join a collection in Java?

Using the concat() Method. The static method concat() combines two Streams logically by creating a lazily concatenated Stream whose elements are all the elements of the first Stream followed by all the elements of the second Stream.

How do I join a stream in Java?

concat() in Java. Stream. concat() method creates a concatenated stream in which the elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel.

How do you join a stream of strings?

Join stream of strings – examplejoining() method takes separator string as argument and join all the strings in the stream using using this separator. For example, we use comma as separator then this method will result into a comma-separated string. Program output.

How do you join a list element in Java?

In Java, we can use String. join(",", list) to join a List String with commas.


1 Answers

One way to perform a full outer join is to first construct a Map<String, Map<String, Object>> that links the month value to the maps themselves and get the values in a list:

//first concatenate the two lists
Map<String, Map<String, Object>> result = Stream.concat(list1.stream(),
                                                        list2.stream())
                //then collect in a map where the key is the value of the month
                .collect(toMap(m -> (String) m.get("Month"),
                //the value is the map itself
                               m -> m,
                //merging maps (i.e. adding the "Sales" and "NoOfTranx" infos)
                               (m1, m2) -> {m1.putAll(m2); return m1; }));

//finally put that in a list
List<Map<String, Object>> merge = new ArrayList<>(result.values());

Notes:

  • the original maps are modified - if this is undesirable you can create a new HashMap<>() in the merging part.
  • for left/right outer join, you can stream one list only and add the relevant entries in the stream
  • for inner join you can start from one of the list, filter elements present in the other list and continue as above

Full example below which prints:

list1 = [{Month=August-13, Sales=282200}, {Month=July-13, Sales=310400}]
list2 = [{Month=August-13, NoOfTranx=6700}, {Month=July-13, NoOfTranx=14400}]
merge = [{Month=August-13, Sales=282200, NoOfTranx=6700}, {Month=July-13, Sales=310400, NoOfTranx=14400}]

Code:

public static void main(String[] args) {
    List<Map<String, Object>> list1 = new ArrayList<>();
    list1.add(map("Month", "August-13", "Sales", 282200));
    list1.add(map("Month", "July-13", "Sales", 310400));
    System.out.println("list1 = " + list1);

    List<Map<String, Object>> list2 = new ArrayList<>();
    list2.add(map("Month", "August-13", "NoOfTranx", 6700));
    list2.add(map("Month", "July-13", "NoOfTranx", 14400));
    System.out.println("list2 = " + list2);

    Map<String, Map<String, Object>> result = Stream.concat(list1.stream(),
                                                            list2.stream())
                .collect(toMap(m -> (String) m.get("Month"),
                               m -> m,
                               (m1, m2) -> {m1.putAll(m2); return m1; }));

    List<Map<String, Object>> merge = new ArrayList<>(result.values());
    System.out.println("merge = " + merge);
}

private static Map<String, Object> map(Object... kvs) {
    Map<String, Object> map = new HashMap<>();
    for (int i = 0; i < kvs.length; i += 2) {
        map.put((String) kvs[i], kvs[i+1]);
    }
    return map;
}
like image 189
assylias Avatar answered Sep 16 '22 13:09

assylias