简体   繁体   中英

Stream Api - split by comma exclude nested commas

I have the code below and I am testing it online here . Also had a look at this post . I am not the best at regular expressions. Basically I am using the stream API to spit a string containing no inner quotes(double/single). Its just a plain string which will never contain any quotes. I am trying to use the stream API to split up the string by commas into key value pairs and put it into a map. However the split is also splitting the requestparams=[id=4, isId=23] into this isId=23], requestparams=[id=4 . its all messed up.

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

class Main {
  public static void main(String[] args) {
    String dataPts = "requestparams=[id=4, isId=23], requestid=12345678, channel=BATCH";

    Map<String, String> reconstructedMap = Arrays.stream(dataPts.split(",")).map(s -> s.split("=",2)).collect(Collectors.toMap(s -> s[0], s -> s[1]));

    System.out.println(reconstructedMap);
  }
}

The above logic produces { requestid=12345678, isId=23], requestparams=[id=4, channel=BATCH} . The [ ] and everything inside should remain as is. I should see {requestparams=[id=4, isId=23], requestid=12345678, channel=BATCH}

The solution I came up with is to clip out the requestparams=[id=4, isId=23] totally from the string using a regular expression as seen in the method below. Then add it back into the map at the end. Its seems messy and unusual.

Map<String,String> convertDataPtsFromStringToMap(String myData{ 
    Pattern pattern = Pattern.compile("requestparams=(.*?])");//value alone [id=4, isId=23]
    Matcher matcher = pattern.matcher(myData);
    String reqParamsValue = "[]";

    if(matcher.find()) {
        reqParamsValue = matcher.group(1);
        myData = myData.replaceAll("(requestparams.*?]),", "");//replace requestparams=[id=4, isId=23]
    }

    Map<String, String> reconstructedMap = Arrays.stream(dataPts.split(",")).map(s -> s.split("=",2)).collect(Collectors.toMap(s -> s[0], s -> s[1]));
    reconstructedMap.put("requestparams", reqParamsValue);//add back the requestparams and its value to the resulting map
    return reconstructedMap;
}

This requestparams will be the only value with [ ] and will not be changed, its just that it has to be in the string. That is whay i can strip it off and put it back in. But now my unit tests will require that property to always be in the string, which is not a problem. It just seems like too much. Looking for a more elegant solution.

Is there a better way using the Streams-Api?

Here is one approach using a formal Java regex pattern matcher:

String dataPts = "requestparams=[id=4, isId=23], requestid=12345678, channel=BATCH";
String pattern = "\\b([^=]+=(?:\\[[^]]+\\]|[^=,]+))(?:,\\s*|$)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(dataPts);
while (m.find()) {
    System.out.println(m.group(1));
}

This prints:

requestparams=[id=4, isId=23]
requestid=12345678
channel=BATCH

Here is an explanation of the regex logic:

\b
(                  capture the following
    [^=]+          a LHS key
    =              =
    (?:
        \[[^]]+\]  either a RHS term in square brackets (check for this first)
        |          OR
        [^=,]+     another term not in brackets
    )
)                  end capture
(?:,\\s*|$)        then match either comma followed by whitespace, or the end of the string

If you wanted to populate a map with keys/values, then use:

String dataPts = "requestparams=[id=4, isId=23], requestid=12345678, channel=BATCH";
Map<String, String> map = new HashMap<>();
String pattern = "\\b([^=]+)=(\\[[^]]+\\]|[^=,]+)(?:,\\s*|$)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(dataPts);
while (m.find()) {
    map.put(m.group(1), m.group(2));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM