I have a string like this:
pet:cat::car:honda::location:Japan::food:sushi
Now :
indicates key-value pairs while ::
separates the pairs.
I want to add the key-value pairs to a map.
I can achieve this using:
Map<String, String> map = new HashMap<String, String>();
String test = "pet:cat::car:honda::location:Japan::food:sushi";
String[] test1 = test.split("::");
for (String s : test1) {
String[] t = s.split(":");
map.put(t[0], t[1]);
}
for (String s : map.keySet()) {
System.out.println(s + " is " + map.get(s));
}
But is there an efficient way of doing this?
I feel the code is inefficient because I have used 2 String[]
objects and called the split
function twice.
Also, I am using t[0]
and t[1]
which might throw an ArrayIndexOutOfBoundsException
if there are no values.
Split is used to break a delimited string into substrings. You can use either a character array or a string array to specify zero or more delimiting characters or strings. If no delimiting characters are specified, the string is split at white-space characters.
To split strings in list into key-value pairs: Use a generator expression to split the strings in the list into nested lists of key-value pairs. Pass the two-dimensional list to the dict() class.
Method 1: Split dictionary keys and values using inbuilt functions. Here, we will use the inbuilt function of Python that is . keys() function in Python, and . values() function in Python to get the keys and values into separate lists.
Using Guava library it's a one-liner:
String test = "pet:cat::car:honda::location:Japan::food:sushi";
Map<String, String> map = Splitter.on( "::" ).withKeyValueSeparator( ':' ).split( test );
System.out.println(map);
The output:
{pet=cat, car=honda, location=Japan, food=sushi}
This also might work faster than JDK String.split
as it does not create a regexp for "::"
.
Update it even handles correctly the corner case from the comments:
String test = "pet:cat::car:honda::location:Japan::food:sushi:::cool";
Map<String, String> map = Splitter.on( "::" ).withKeyValueSeparator( ':' ).split( test );
System.out.println(map);
The output is:
{pet=cat, car=honda, location=Japan, food=sushi, =cool}
You could do a single call to split() and a single pass on the String using the following code. But it of course assumes the String is valid in the first place:
Map<String, String> map = new HashMap<String, String>();
String test = "pet:cat::car:honda::location:Japan::food:sushi";
// split on ':' and on '::'
String[] parts = test.split("::?");
for (int i = 0; i < parts.length; i += 2) {
map.put(parts[i], parts[i + 1]);
}
for (String s : map.keySet()) {
System.out.println(s + " is " + map.get(s));
}
The above is probably a little bit more efficient than your solution, but if you find your code clearer, then keep it, because there is almost zero chance such an optimization has a significant impact on performance, unless you do that millions of times. Anyway, if it's so important, then you should measure and compare.
EDIT:
for those who wonder what ::?
means in the above code: String.split() takes a regular expression as argument. A separator is a substring that matches the regular expression. ::?
is a regular expression which means: 1 colon, followed by 0 or 1 colon. It thus allows considering ::
and :
as separators.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With