Imii Iik
Imii Iik

Reputation: 205

Aggregate string in array list java

I have an Arraylist of string arrays, already filled by the values below (columns and row)

{"name","sname","Id1","Id2","type","LDP","oldvalue","newvalue"}
{"test1","abc","20","50","t1","SD1","0","1"}
{"test2","znc","21","23","t1","SF5","3","4"}
{"test1","abc","20","50","t1","SD3","0","1"}
{"test1","HJc","53","50","t1","SD3","0","1"}
{"test2","znc","21","23","t1","SF1","1","6"}
{"test1","abc","20","50","t1","SD5","2","19"}
{"test3","ldb","19","54","t1","SR51","6","1"}
{"test2","znc","21","23","t1","SF12","17","36"}
{"test3","ldb","19","54","t1","SR44","19","31"}
{"test4","lYI","76","56","t1","TB77","54","87"}

I want have a new Arraylist by sorting this current Arraylist and get the lines with the same keys (Order by : name,sname,Id1,Id2,type), concatenate their values in one column (separated by ;) in one line.

Expected output:

{"name","sname","Id1","Id2","type","Comment"}
{"test1","abc","20","50","t1","SD1,0,1; SD3,0,1; SD5,2,19"}
{"test1","HJc","53","50","t1","SD3,0,1"}
{"test2","znc","21","23","t1","SF5,3,4; SF1,1,6; SF12,17,36"}
{"test3","ldb","19","54","t1","SR44,19,31;SR51,6,1 }
{"test4","lYI","76","56","t1","TB77,54,87"}

My Arraylist is generated from a result query:

 // header
     String[] myString0 = {"name","sname","Id1","Id2","type","LDP","oldvalue","newvalue"};
    //lines
     while (rset.next()) {

                                String name = rset.getString("name");
                                String sname = rset.getString("sname");
                                String Id1 = rset.getString("Id1");
                                String Id2 = rset.getString("Id2");
                                String type = rset.getString("type");
                                String LDP = rset.getString("LDP");
                                String oldvalue = rset.getString("oldvalue");
                                String newvalue = rset.getString("newvalue");

                                String[] myString1 = {name, sname, Id1, Id2, "type", LDP, oldvalue, newvalue};

                                outerArr.add(myString1);// my Arraylist
                            }
                        }

Thanks,

Upvotes: 0

Views: 2445

Answers (2)

shmosel
shmosel

Reputation: 50726

Here's a solution using Streams, with a bit of help from Guava's Ordering utility:

public static List<String[]> aggregate(List<String[]> data) {
    List<String[]> aggregated = data.stream()
            .skip(1)
            .map(Arrays::asList)
            .collect(Collectors.groupingBy(
                    a -> a.subList(0, 5),
                    () -> new TreeMap<>(
                            Ordering.from(String.CASE_INSENSITIVE_ORDER)
                                    .lexicographical()),
                    Collectors.mapping(
                            a -> String.join(",", a.subList(5, 8)),
                            Collectors.joining("; "))))
            .entrySet()
            .stream()
            .map(e -> Stream.concat(
                    e.getKey().stream(),
                    Stream.of(e.getValue())))
            .map(s -> s.toArray(String[]::new))
            .collect(Collectors.toCollection(ArrayList::new));

    aggregated.add(0, new String[] {"name","sname","Id1","Id2","type","Comment"});

    return aggregated;
}

Test:

public static void main(String[] args) {
    List<String[]> data = Arrays.asList(new String[][] {
            {"name","sname","Id1","Id2","type","LDP","oldvalue","newvalue"},
            {"test1","abc","20","50","t1","SD1","0","1"},
            {"test2","znc","21","23","t1","SF5","3","4"},
            {"test1","abc","20","50","t1","SD3","0","1"},
            {"test1","HJc","53","50","t1","SD3","0","1"},
            {"test2","znc","21","23","t1","SF1","1","6"},
            {"test1","abc","20","50","t1","SD5","2","19"},
            {"test3","ldb","19","54","t1","SR51","6","1"},
            {"test2","znc","21","23","t1","SF12","17","36"},
            {"test3","ldb","19","54","t1","SR44","19","31"},
            {"test4","lYI","76","56","t1","TB77","54","87"}
    });

    aggregate(data)
            .stream()
            .map(Arrays::toString)
            .forEach(System.out::println);
}

Output:

[name, sname, Id1, Id2, type, Comment]
[test1, abc, 20, 50, t1, SD1,0,1; SD3,0,1; SD5,2,19]
[test1, HJc, 53, 50, t1, SD3,0,1]
[test2, znc, 21, 23, t1, SF5,3,4; SF1,1,6; SF12,17,36]
[test3, ldb, 19, 54, t1, SR51,6,1; SR44,19,31]
[test4, lYI, 76, 56, t1, TB77,54,87]

Upvotes: 1

Trevor Freeman
Trevor Freeman

Reputation: 7242

  1. Create your own key class for the first 5 columns, or concatenate them into a string (may or may not be adequate for your use case).
  2. Add everything to a map keyed by your key class, with a String, StringBuilder, or List for your values / concatenated fields
  3. After you have parsed all the data into the map, then iterate the map to put everything back into a list, looping to concatenate the values for each key
  4. Sort the new list according to sorting preferences (or alternatively, maintain a sorted map using a LinkedHashMap initially).

The above is probably easier to do using a guava ArrayListMultiMap.

E.g. something like

// for each row...
myArrayListMultiMap.put(new MyKey(name, sname, id1, id2, type), LDP + "," + oldValue + "," + newValue);

// then
for (MyKey key : myArrayListMultiMap.keySet()) {
    List<String> values = myArrayListMultiMap.get(key);
    String concatenated = StringUtils.join(values, ";");
    myList.add(new Row(entry.getKey(), concatenated));
}

Collections.sort(myList, myComparator);

Important note: make sure that your MyKey class implements hashCode and equals.

Upvotes: 1

Related Questions