There is no need to reinvent the wheel. The Google Guava library provides the Splitter class.
Here's how you can use it along with some test code:
package com.sandbox;
import com.google.common.base.Splitter;
import org.junit.Test;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class SandboxTest {
@Test
public void testQuestionInput() {
Map<String, String> map = splitToMap("A=4 H=X PO=87");
assertEquals("4", map.get("A"));
assertEquals("X", map.get("H"));
assertEquals("87", map.get("PO"));
}
private Map<String, String> splitToMap(String in) {
return Splitter.on(" ").withKeyValueSeparator("=").split(in);
}
}
Answer from Daniel Kaplan on Stack OverflowThere is no need to reinvent the wheel. The Google Guava library provides the Splitter class.
Here's how you can use it along with some test code:
package com.sandbox;
import com.google.common.base.Splitter;
import org.junit.Test;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class SandboxTest {
@Test
public void testQuestionInput() {
Map<String, String> map = splitToMap("A=4 H=X PO=87");
assertEquals("4", map.get("A"));
assertEquals("X", map.get("H"));
assertEquals("87", map.get("PO"));
}
private Map<String, String> splitToMap(String in) {
return Splitter.on(" ").withKeyValueSeparator("=").split(in);
}
}
Java 8 to the rescue!
import static java.util.stream.Collectors.*;
Map<String, String> result = Arrays.stream(input.split(" "))
.map(s -> s.split("="))
.collect(Collectors.toMap(
a -> a[0], //key
a -> a[1] //value
));
NOTE: Assuming no duplicates. Otherwise look into the 3rd 'mergeFunction' argument.
collections - How to convert String into Hashmap in java - Stack Overflow
lambda - Java 8: How to convert String to Map<String,String>? - Stack Overflow
apex - How to convert Map<String,Object> into Map<string,string>()? - Salesforce Stack Exchange
How can I convert a string to a map?
This is one solution. If you want to make it more generic, you can use the StringUtils library.
String value = "{first_name = naresh,last_name = kumar,gender = male}";
value = value.substring(1, value.length()-1); //remove curly brackets
String[] keyValuePairs = value.split(","); //split the string to creat key-value pairs
Map<String,String> map = new HashMap<>();
for(String pair : keyValuePairs) //iterate over the pairs
{
String[] entry = pair.split("="); //split the pairs to get key and value
map.put(entry[0].trim(), entry[1].trim()); //add them to the hashmap and trim whitespaces
}
For example you can switch
value = value.substring(1, value.length()-1);
to
value = StringUtils.substringBetween(value, "{", "}");
if you are using StringUtils which is contained in apache.commons.lang package.
In a single line you can convert any type of object to any other type of object.
(Since I use Gson quite liberally, I am sharing a Gson based approach)
Gson gson = new Gson();
Map<Object,Object> attributes = gson.fromJson(gson.toJson(value),Map.class);
What it does is:
gson.toJson(value)will serialize your object into its equivalent Json representation.gson.fromJsonwill convert the Json string to specified object. (in this example -Map)
There are 2 advantages with this approach:
- The flexibility to pass any Object instead of String to
toJsonmethod. - You can use this single line to convert to any object even your own declared objects.
Split the string by , to get individual map entries. Then split them by = to get the key and the value.
Map<String, String> reconstructedUtilMap = Arrays.stream(utilMapString.split(","))
.map(s -> s.split("="))
.collect(Collectors.toMap(s -> s[0], s -> s[1]));
Note: As pointed out by Andreas@ in the comments, this is not a reliable way to convert between a map and a string
EDIT: Thanks to Holger for this suggestion.
Use s.split("=", 2) to ensure that the array is never larger than two elements. This will be useful to not lose the contents (when the value has =)
Example: when the input string is "a=1,b=2,c=3=44=5555"
you will get {a=1, b=2, c=3=44=5555}
Earlier (just using s.split("=")) will give
{a=1, b=2, c=3}
Here is another option which streams a list of 1=1 etc. terms into a map.
String input = "1=1,2=2,3=3,4=4,5=5";
Map<String, String> map = Arrays.asList(input.split(",")).stream().collect(
Collectors.toMap(x -> x.replaceAll("=\\d+$", ""),
x -> x.replaceAll("^\\d+=", "")));
System.out.println(Collections.singletonList(map));
[{1=1, 2=2, 3=3, 4=4, 5=5}]
So you can try like this
map<string,string> newMap= new Map<string,string>();
for(String strKey: mapValues.keyset())
{
newMap.put(strKey, String.valueof(mapValues.get(strKey)));
}
I have tried this worked for me:
enter code here
map<string,object> mspstrToObj = new Map<string,object>();
mspstrToObj.put('key1', 'obj1');
map<string,string> mspstrTostr = new Map<string,string>();
mspstrTostr.put('strKey1',string.valueof(mspstrToObj.get('key1')));
system.debug('=======mspstrTostr====='+mspstrTostr);
You need to create new Map and put the values as per above.
My use case is I have an optional block in a resource that I'm trying to templatize.
That block has only one parameter: a number. instead of a user creating a map variable in the root, I want him to be able to just put in a number.
But dynamic blocks only take maps as an input. Any idea what I can do?
To add, that block parameter is named 'count'. Which Terraform is throwing a fit over...what can I do!?
Use Object#toString().
String string = map.toString();
That's after all also what System.out.println(object) does under the hoods. The format for maps is described in AbstractMap#toString().
Returns a string representation of this map. The string representation consists of a list of key-value mappings in the order returned by the map's
entrySetview's iterator, enclosed in braces ("{}"). Adjacent mappings are separated by the characters ", " (comma and space). Each key-value mapping is rendered as the key followed by an equals sign ("=") followed by the associated value. Keys and values are converted to strings as byString.valueOf(Object).
You can also use google-collections (guava) Joiner class if you want to customize the print format
Joiner.on(",").withKeyValueSeparator("=").join(map);
I have to convert this
[(โ2โ,โ7โ),(โ3โ,โ8โ)] // array of dictionaries as a string in a text file
to a hashmap that will look like HashMap<String, String>().
for coverting my hashmap to a string I have this:
String mapAsString = map.keySet().stream()
.map(key -> key + "," + map.get(key))
.collect(Collectors.joining(", ", "(", ")"));But its not my exact output that I need.
How can I convert this back and forth in java using java lamba expressions?
You can do the following
- Removing the
{and}characters from the start and end the string. Do not usereplacein case there are any occurrences inside it. - Split the result into each discrete chunk that forms key-value pairs.
- Split those into actual key and value
- The result can readily be convert to a Map because the constructor takes an array where each item is an array with two items and will convert that to a map where the first item is the key, the second the value:
let string = "{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}";
let keyValuePairs = string.slice(1, -1) //remove first and last character
.split(/\s*,\s*/) //split with optional spaces around the comma
.map(chunk => chunk.split("=")); //split key=value
const map = new Map(keyValuePairs);
console.log(map.get("executionid"));
console.log(map.get("timeout"));
You can work without regexps too, but you have to understand the basic concept of that first you split along the ,s, and then along the =s:
var data = "{executionid=0c3246fb37e65e3368c8c4f30000016ab593bec244daa8df, timeout=10000}";
var pairs = data.substring(1, data.length - 1).split(", "); // step 1, split using commas
var obj = pairs.reduce(function(acc, cur) {
var pair = cur.split("="); // step 2, split using =
acc[pair[0].trim()] = pair[1].trim();
return acc;
}, {});
console.log(obj);
That's not possible.
If you can change the string to valid JSON, you can use
import 'dart:convert';
...
Map valueMap = json.decode(value);
// or
Map valueMap = jsonDecode(value);
The string would need to look like
{"first_name" : "fname","last_name" : "lname","gender" : "male", "location" : { "state" : "state", "country" : "country", "place" : "place"} }
You would have to change the way you create the string.
I'm guessing you are creating the string using the yourMap.toString() method. You should rather use json.encode(yourMap), which converts your map to valid JSON, which you can the parse with json.decode(yourString).
One simple way is to use str_to_map function after you get rid of the double quotes from PersonalInfo column:
val df1 = df.withColumn(
"PersonalInfo",
expr("str_to_map(regexp_replace(PersonalInfo, '\"', ''))")
)
df1.show(false)
//+-------+-------+------------------------------------------------------------------------------+
//|Empcode|EmpName|PersonalInfo |
//+-------+-------+------------------------------------------------------------------------------+
//|1 |abc |{email -> abc@gmail.com, Location -> India, Gender -> Male} |
//|2 |xyz |{email -> xyz@gmail.com, Location -> US} |
//|3 |pqr |{email -> abc@gmail.com, Gender -> Female, Location -> Europe, Mobile -> 1234}|
//+-------+-------+------------------------------------------------------------------------------+
If you want to create a map from PersonalInfo column, from Spark 3.0 you can proceed as follows:
- Split your string according to
"",""usingsplitfunction - For each element of your obtained string array, create sub-arrays according to
"":""usingsplitfunction - Remove all
""from elements of sub-arrays usingregexp_replacefunction - Build map entries using
structfunction - Use
map_from_entriesto build map from your array of entries
Complete code is as follows:
import org.apache.spark.sql.functions.{col, map_from_entries, regexp_replace, split, struct, transform}
val result = data.withColumn("PersonalInfo",
map_from_entries(
transform(
split(col("PersonalInfo"), "\"\",\"\""),
item => struct(
regexp_replace(split(item, "\"\":\"\"")(0), "\"\"", ""),
regexp_replace(split(item, "\"\":\"\"")(1), "\"\"", "")
)
)
)
)
With the following input_dataframe:
+-------+-------+---------------------------------------------------------------------------------------------+
|Empcode|EmpName|PersonalInfo |
+-------+-------+---------------------------------------------------------------------------------------------+
|1 |abc |""email"":""abc@gmail.com"",""Location"":""India"",""Gender"":""Male"" |
|2 |xyz |""email"":""xyz@gmail.com"",""Location"":""US"" |
|3 |pqr |""email"":""abc@gmail.com"",""Gender"":""Female"",""Location"":""Europe"",""Mobile"":""1234""|
+-------+-------+---------------------------------------------------------------------------------------------+
You get the following result dataframe:
+-------+-------+------------------------------------------------------------------------------+
|Empcode|EmpName|PersonalInfo |
+-------+-------+------------------------------------------------------------------------------+
|1 |abc |{email -> abc@gmail.com, Location -> India, Gender -> Male} |
|2 |xyz |{email -> xyz@gmail.com, Location -> US} |
|3 |pqr |{email -> abc@gmail.com, Gender -> Female, Location -> Europe, Mobile -> 1234}|
+-------+-------+------------------------------------------------------------------------------+