-2

I have receive string

String message = "Value{A=10,B=20,C=30,D=700-2-1, Bourke STREET, SOUTH 2/28 QUEEN ST,E=40,F=50}";
Map<Object, Object> = {
       A = 10 ,
       B = 20
       C = 30
       D = 700-2-1, Bourke STREET, SOUTH 100/28 QUEEN ST
       E = 40
       F = 50
}

I am looking for a generic approach. Where

  1. Need All values of A,B,C ....

  2. The order of A,B,C,D,E and F will change

  3. Only D may contain single or multiple commas(,) in its value or no comma

Karthik
  • 1
  • 1
  • 2
    Does this answer your question? [How to convert String into Hashmap in java](https://stackoverflow.com/questions/26485964/how-to-convert-string-into-hashmap-in-java) – Nuwan Harshakumara Piyarathna May 03 '20 at 04:23
  • @NuwanHarshakumaraPiyarathna No, that question was a bit straight, Here in my case, Value also contains *,* and the order of keys are not consistent sometimes A comes first and sometimes A in the end – Karthik May 03 '20 at 04:37
  • @Karthikwhile converting to a `Map`(default `HashMap`) you should be aware that the order of keys shouldn't matter at first and then the question is an exact duplicate of the above link. – Naman May 03 '20 at 07:12
  • Can we assume that neither `D` nor any other value contains an equal sign, `=`? – Ole V.V. May 03 '20 at 08:28
  • well, no other value contains =, at this point – Karthik May 04 '20 at 03:34

2 Answers2

1

I am thinking String.split(). We first want to split the part of the message inside the curly braces at commas, then at equal signs. However, not at every comma, obviously. Only at commas that go right before a new key letter and an equal sign. In code:

String message
     = "Value{A=10,B=20,C=30,"D=700-2-1, Bourke STREET, SOUTH 2/28 QUEEN ST,E=40,F=50}";

String contents = message.replaceFirst("^Value\\{(.*)\\}$", "$1");
String[] pairs = contents.split(",(?=[ABCDEF]=)");
Map<String, String> m = Arrays.stream(pairs)
        .map(p -> p.split("=", 2))
        .collect(Collectors.toMap(a -> a[0], a -> a[1]));

m.forEach((k, v) -> System.out.println(k + " -> " + v));

Output is:

A -> 10
B -> 20
C -> 30
D -> 700-2-1, Bourke STREET, SOUTH 2/28 QUEEN ST
E -> 40
F -> 50

(?=[ABCDEF]=) in the second regular expression is a positive lookahead. It makes sure that we only match the comma if it is followed by one of those letters and en equal sign. If letters can be other than ABCDEF, you may want to use \w for a word character instead of [ABCDEF].

We don’t necessarily need a stream operation, but you had tagged your question java-stream, so I thought you would like to see one.

The stream operation is not guaranteed to give you a HashMap. Even if you observe that it does (which it did on Java 11 in my case), it may not on the next Java version or even with different input. For the majority of cases this should be no concern. If you have a specific reason for needing to be sure, check what you got and convert if it wasn’t a HashMap:

if (! m.getClass().equals(HashMap.class)) {
    m = new HashMap<>(m);
}
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

This code will work for above scenario :


public static void main(String... args) {
        String message = "Value{A=10,B=20,C=30,D=700-2-1, Bourke STREET, SOUTH 2/28 QUEEN ST,E=40,F=50}";
        //remove value and curly braces
        message = message.substring(6,message.length()-1);
        //split by comma followed by capital letter
        String[] values= message.split("(?<=,)(?=[A-Z])");      
        //split and collect to map
        Map<String, String> map = Arrays.asList(values).stream()
        .map(x-> x.lastIndexOf(",")>-1?x.substring(0, x.lastIndexOf(",")):x)
        .map(x-> x.split("="))      
        .collect(Collectors.toMap(x -> x[0], x-> x[1]));
        //print map 
        System.out.println(map);
    }
Hemant
  • 1,403
  • 2
  • 11
  • 21
  • There are only minor differences between your code and mine. I tried your code with the `D` key last: `Value{A=10,B=20,C=30,E=40,F=50,D=700-2-1, Bourke STREET, SOUTH 2/28 QUEEN ST}`, though (since the OP said *The order of A,B,C,D,E and F will change*). I got `{A=10, B=20, C=30, D=700-2-1, Bourke STREET, E=40, F=50}`. The `, SOUTH 2/28 QUEEN ST` bit is missing. – Ole V.V. May 03 '20 at 09:08