Shiladittya Chakraborty
Shiladittya Chakraborty

Reputation: 4418

Store data into map group wise

I have one string for example :

2014@2@200@0#2014@2@200@0#2012@2@200@0#2012@2@200@0#2011@2@200@0

Now what I need to store the above details into one map with below rule:

  1. Split above string using '#'
  2. Again split the sub string using @
  3. After splitting store the data into map

For example if we split above string using # then we can get below data into string array :

array[0] = "2014@2@200@0";
array[1] = "2014@2@200@0";
array[2] = "2012@1@100@0";
array[3] = "2012@3@200@0";
array[4] = "2011@2@200@0";

Now again split the array data using '@'.

So we get :

a[0] = "2014";
a[1] = "2";
a[2] = "200";
a[3] = "0";

Map look like : Map"String, TestClass" test;

TestClass {
   String a1;
   String a2;
   String s3;
   String a4;
} 

Map key : a[0] value

I need to group those data by a[0] value.

For example map data for 2014 key :

key : 2014
value : a4 = 2014, a1 = 2+2, a2 = 200 + 200, a3 = 0 + 0

key : 2012
value : a4 = 2012, a1 = 1+3, a2 = 100 + 200, a3 = 0 + 0

How to achieve the above case?

Upvotes: 1

Views: 74

Answers (4)

Ivaylo Toskov
Ivaylo Toskov

Reputation: 4031

Here is a short solution using Java 8:

TestSplit.java

import java.util.stream.Stream;

public class TestSplit {
    public static void main (String... args) {
        Map<String, TestClass> map = split("2014@2@200@0#2014@2@200@0#2012@1@100@0#2012@3@200@0#2011@2@200@0");
        map.forEach((key, value) -> System.out.println(key + " -> " + value));
    }

    private static Map<String, TestClass> split(String input) {
        String[] testClassStrings = input.split("#");
        Stream<String[]> testClassStringsStream = Arrays.stream(testClassStrings).map(s -> s.split("@"));
        Stream<TestClass> testClasses = testClassStringsStream.map(s -> new TestClass(s[0], s[1], s[2], s[3]));
        Map<String, TestClass> testClassesMap = new HashMap<>();
        testClasses.forEach((TestClass tc) -> {
            TestClass oldValue = testClassesMap.get(tc.a0);
            testClassesMap.put(tc.a0, oldValue == null ? tc : new TestClass(oldValue, tc));
        });

        return testClassesMap;
    }
}

TestClass.java

class TestClass {
    String a0;
    String a1;
    String a2;
    String a3;

    public TestClass(String a0, String a1, String a2, String a3) {
        this.a0 = a0;
        this.a1 = a1;
        this.a2 = a2;
        this.a3 = a3;
    }

    public TestClass(TestClass tc1, TestClass tc2) {
        this.a0 = tc1.a0;
        this.a1 = tc1.a1 + " + " + tc2.a1;
        this.a2 = tc1.a2 + " + " + tc2.a2;
        this.a3 = tc1.a3 + " + " + tc2.a3;
    }

    @Override
    public String toString() {
        return String.format("a0 = %s, a1 = %s, a3 = %s, a4 = %s", a0, a1, a2, a3);
    }
}

All you need to do is invoke the split method in the TestSplit class. The method should be concise and readable, but with a bit more effort you can make it even more functional. Here are the precise steps:

  1. Split the string using # (line String[] testClassStrings = input.split("#");). That will perform the following transformation: "2014@2@200@0#2014@2@200@0#2012@1@100@0#2012@3@200@0#2011@2@200@0" to

    testClassStrings[0] = "2014@2@200@0"
    testClassStrings[1] = "2014@2@200@0"
    testClassStrings[2] = "2012@1@100@0"
    testClassStrings[3] = "2012@3@200@0"
    testClassStrings[4] = "2011@2@200@0"
    
  2. Split each string using @. (line Stream<String[]> testClassStringsStream = Arrays.stream(testClassStrings).map(s -> s.split("@"));. Now you have a stream where each entry is an array of something like ["2014", "2", "200", "0"].

  3. From each string build a new TestClass with the line Stream<TestClass> testClasses = testClassStringsStream.map(s -> new TestClass(s[0], s[1], s[2], s[3]));.

  4. Iterate over all test classes and add them to the map testClassesMap. In case certain test class is already contained in the map, apply the addition of its elements:

    Map<String, TestClass> testClassesMap = new HashMap<>();
    testClasses.forEach((TestClass tc) -> {
        TestClass oldValue = testClassesMap.get(tc.a0);
        testClassesMap.put(tc.a0, oldValue == null ? tc : new TestClass(oldValue, tc));
    });
    

Running the main method in TestSplit will produce:

2014 -> a0 = 2014, a1 = 2 + 2, a3 = 200 + 200, a4 = 0 + 0
2012 -> a0 = 2012, a1 = 1 + 3, a3 = 100 + 200, a4 = 0 + 0
2011 -> a0 = 2011, a1 = 2, a3 = 200, a4 = 0

Upvotes: 1

Arpit Aggarwal
Arpit Aggarwal

Reputation: 29316

You can use Java - 8 Stream to accomplish it, as follows:

Stream.of(str.split("#")).map(e -> e.split("@")).map(x -> new TestClass(x[1], x[2], x[3], x[0])).collect(Collectors.toMap(TestClass::getA4, z -> z,(p1, p2) -> p1));

Example implementation though you have to tweak logic a bit:

SplitString.java

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class SplitString {

    public static void main(String[] args) {
        Map<String, TestClass> map = Stream.of(str.split("#")).map(e -> e.split("@")).map(x -> new TestClass(x[1], x[2], x[3], x[0])).collect(Collectors.toMap(TestClass::getA4, z -> z,(p1, p2) -> p1));
        System.out.println(map);
    }
}

TestClass.java

public class TestClass {

    private final String a1;
    private final String a2;
    private final String a3;
    private final String a4;

    public TestClass(String a1, String a2, String a3, String a4) {
        this.a1 = a1;
        this.a2 = a2;
        this.a3 = a3;
        this.a4 = a4;
    }

    public String getA1() {
        return a1;
    }

    public String getA2() {
        return a2;
    }

    public String getA3() {
        return a3;
    }

    public String getA4() {
        return a4;
    }

    @Override
    public String toString() {
      return "TestClass [a4=" + a4 + ", a1=" + a1 + ", a2=" + a2 + ", a3="
            + a3 + "]";
}

}

Output:

{2014=TestClass [a4=2014, a1=2, a2=200, a3=0], 2012=TestClass [a4=2012, a1=2, a2=200, a3=0], 2011=TestClass [a4=2011, a1=2, a2=200, a3=0]}

Upvotes: 0

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48733

You need to create a custom method that joins all the grouped TestClass field data.

In Java 8, you can easily map/join data using the stream interface.

DataMapper

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class DataMapper {
    public static String data = "2014@2@200@0#2014@2@200@0#2012@1@100@0#2012@3@200@0#2011@2@200@0";

    public static void main(String[] args) {
        Map<String, List<TestClass>> map = parse(data, "#", "@");
        Iterator<Map.Entry<String, List<TestClass>>> iterator = map.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry<String, List<TestClass>> key = iterator.next();

            String a1 = joinInstanceFieldValues(key.getValue(), t -> t.getA1(), " + ");
            String a2 = joinInstanceFieldValues(key.getValue(), t -> t.getA2(), " + ");
            String a3 = joinInstanceFieldValues(key.getValue(), t -> t.getA3(), " + ");

            System.out.printf("key : %4$s%nvalue : a4 = %4$s, a1 = %1$s, a2 = %2$s, a3 = %3$s  %n%n", a1, a2, a3, key.getKey());
        }
    }

    public static Map<String, List<TestClass>> parse(String data, String delimOuter, String delimInner) {
        Map<String, List<TestClass>> result = new HashMap<>();
        String tokens[] = data.split(delimOuter);

        for (String value : tokens) {
            TestClass test = TestClass.parse(value, delimInner);
            String key = test.getA4();
            List<TestClass> list = result.containsKey(key) ? result.get(key) : new ArrayList<>();

            list.add(test);
            result.put(key, list);
        }

        return result;
    }

    private static <T> String joinInstanceFieldValues(List<T> list, Function<T, String> func, String delimiter) {
        return list.stream().map(func).collect(Collectors.joining(delimiter));
    }
}

TestClass

public class TestClass {
    private String a1;
    private String a2;
    private String a3;
    private String a4;

    public String getA1() { return a1; }
    public String getA2() { return a2; }
    public String getA3() { return a3; }
    public String getA4() { return a4; }

    public TestClass(String a1, String a2, String a3, String a4) {
        this.a1 = a1;
        this.a2 = a2;
        this.a3 = a3;
        this.a4 = a4;
    }

    @Override
    public String toString() {
        return String.format("a4 = %4$s, a1 = %1$s, a2 = %2$s, a3 = %3$s", a1, a2, a3, a4);
    }

    public static TestClass parse(String input, String delimiter) throws IllegalArgumentException {
        String[] data = input.split(delimiter);

        if (data.length != 4) {
            throw new IllegalArgumentException("Invalid number of tokens: " + data.length);
        }

        return new TestClass(data[1], data[2], data[3], data[0]);
    }
}

Output

key : 2014
value : a4 = 2014, a1 = 2 + 2, a2 = 200 + 200, a3 = 0 + 0  

key : 2012
value : a4 = 2012, a1 = 1 + 3, a2 = 100 + 200, a3 = 0 + 0  

key : 2011
value : a4 = 2011, a1 = 2, a2 = 200, a3 = 0  

Upvotes: 0

Atul
Atul

Reputation: 1556

Try this

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class Test 
{
String a1;
String a2;
String a3;
String a4;


Test(String[] str)
{
    a1=str[0];
    a2=str[1]+"+"+str[1];
    a3=str[2]+"+"+str[2];
    a4=str[3]+"+"+str[3];
}

public static void main(String[] args)
{
    String str="2014@2@200@0#2014@2@200@0#2012@2@200@0#2012@2@200@0#2011@2@200@0";

    String arr[]=str.split("#");

    Map<String,Test> map=new HashMap<String,Test>();
    for (String value : arr) 
    {
        String s[]=value.split("@");
        Test test=new Test(s);
        map.put(s[0], test);
    }
    for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) 
    {
        Entry key=(Entry) iterator.next();
        Test t1=map.get(key.getKey());
        System.out.println("Map Key:"+key.getKey());
        System.out.print("\ta1: "+t1.a1);
        System.out.print("\ta2: "+t1.a2);
        System.out.print("\ta3: "+t1.a3);
        System.out.print("\ta4: "+t1.a4);
        System.out.println();
    }       
}
}

Output:

Map Key:2014
    a1:2014 a2:2+2  a3:200+200  a4:0+0
Map Key:2012
    a1:2012 a2:2+2  a3:200+200  a4:0+0
Map Key:2011
    a1:2011 a2:2+2  a3:200+200  a4:0+0

Upvotes: 0

Related Questions