java invalid json string to map (without quotes on key) [duplicate] - java

How can I convert a String into a HashMap?
String value = "{first_name = naresh, last_name = kumar, gender = male}"
into
Map<Object, Object> = {
first_name = naresh,
last_name = kumar,
gender = male
}
Where the keys are first_name, last_name and gender and the values are naresh, kumar, male.
Note: Keys can be any thing like city = hyderabad.
I am looking for a generic approach.

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.

You can do it in single line, for any object type not just Map.
(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.fromJson will convert the Json string to specified object. (in this example - Map)
There are 2 advantages with this approach:
The flexibility to pass an Object instead of String to toJson method.
You can use this single line to convert to any object even your own declared objects.

String value = "{first_name = naresh,last_name = kumar,gender = male}"
Let's start
Remove { and } from the String>>first_name = naresh,last_name = kumar,gender = male
Split the String from ,>> array of 3 element
Now you have an array with 3 element
Iterate the array and split each element by =
Create a Map<String,String> put each part separated by =. first part as Key and second part as Value

#Test
public void testToStringToMap() {
Map<String,String> expected = new HashMap<>();
expected.put("first_name", "naresh");
expected.put("last_name", "kumar");
expected.put("gender", "male");
String mapString = expected.toString();
Map<String, String> actual = Arrays.stream(mapString.replace("{", "").replace("}", "").split(","))
.map(arrayData-> arrayData.split("="))
.collect(Collectors.toMap(d-> ((String)d[0]).trim(), d-> (String)d[1]));
expected.entrySet().stream().forEach(e->assertTrue(actual.get(e.getKey()).equals(e.getValue())));
}

try this out :)
public static HashMap HashMapFrom(String s){
HashMap base = new HashMap(); //result
int dismiss = 0; //dismiss tracker
StringBuilder tmpVal = new StringBuilder(); //each val holder
StringBuilder tmpKey = new StringBuilder(); //each key holder
for (String next:s.split("")){ //each of vale
if(dismiss==0){ //if not writing value
if (next.equals("=")) //start writing value
dismiss=1; //update tracker
else
tmpKey.append(next); //writing key
} else {
if (next.equals("{")) //if it's value so need to dismiss
dismiss++;
else if (next.equals("}")) //value closed so need to focus
dismiss--;
else if (next.equals(",") //declaration ends
&& dismiss==1) {
//by the way you have to create something to correct the type
Object ObjVal = object.valueOf(tmpVal.toString()); //correct the type of object
base.put(tmpKey.toString(),ObjVal);//declaring
tmpKey = new StringBuilder();
tmpVal = new StringBuilder();
dismiss--;
continue; //next :)
}
tmpVal.append(next); //writing value
}
}
Object objVal = object.valueOf(tmpVal.toString()); //same as here
base.put(tmpKey.toString(), objVal); //leftovers
return base;
}
examples
input : "a=0,b={a=1},c={ew={qw=2}},0=a"
output : {0=a,a=0,b={a=1},c={ew={qw=2}}}

Should Use this way to convert into map :
String student[] = students.split("\\{|}");
String id_name[] = student[1].split(",");
Map<String,String> studentIdName = new HashMap<>();
for (String std: id_name) {
String str[] = std.split("=");
studentIdName.put(str[0],str[1]);
}

You can use below library to convert any string to Map object.
<!-- https://mvnrepository.com/artifact/io.github.githubshah/gsonExtension -->
<dependency>
<groupId>io.github.githubshah</groupId>
<artifactId>gsonExtension</artifactId>
<version>4.1.0</version>
</dependency>

Using Java Stream:
Map<String, String> map = Arrays.stream(value.replaceAll("[{}]", " ").split(","))
.map(s -> s.split("=", 2))
.collect(Collectors.toMap(s -> s[0].trim(), s -> s[1].trim()));
Arrays.stream() to convert string array to stream.
replaceAll("[{}]", " "): regex version to replace both braces.
split(","): Split the string by , to get individual map entries.
s.split("=", 2): Split them by = to get the key and the value and ensure that the array is never larger than two elements.
The collect() method in Stream API collects all objects from a stream object and stored in the type of collection.
Collectors.toMap(s -> s[0].trim(), s -> s[1].trim()): Accumulates elements into a Map whose keys and values are the result of applying the provided mapping functions to the input elements.

Related

Find unique value of string array and keep order

I have a String[] with values like so:
line_str = "1,3,4,3,11,2,2,6,7"
I want to find unique value and keep the arrangement of value
unique_str="1,3,4,11,2,6,7"
I'm using a HashSet but the output is:
[1,6,7,4,11,3,2]
Here is my code:
String line_str = "1,3,4,3,11,2,2,6,7";
String[] str_arr = line_str.split(",");
Set<String> uniqueValue = new HashSet<>(Arrays.asList(str_arr));
Toast.makeText(this, uniqueValue.toString(),Toast.LENGTH_LONG).show();
A HashSet will ensure no duplications and a LinkedHashSet will ensure each element remains in its designated position;
String line_str = "1,3,4,3,11,2,2,6,7";
String[] str_arr = line_str.split(",");
Set<Integer> uniqueNumbers = new LinkedHashSet<Integer>();
for(String num : str_arr) {
uniqueNumbers.add(Integer.parseInt(num));
}
If your input has any variance then you will need to handle that.
Using streams :
String line_str = "1,3,4,3,11,2,2,6,7";
String unique_str = Pattern.compile(",")
.splitAsStream(line_str)
.distinct()
.collect(Collectors.joining(","));
System.out.println(unique_str);

How to store more than one value for same key in HashMap?

I have a string named InputRow, which looks like this:
1,Kit,23
2,Ret,211
I apply the Regex (.+),(.+),(.+) on it and store the results in multiple variables.
For the first line 1,kit,23 I get:
InputRow.1-->1
InputRow.2-->kit
InputRow.3-->23
For the second line 2,Ret,211 I get:
InputRow.1-->2
InputRow.2-->Ret
InputRow.3-->211
I want to store all input rows in a HashMap with the same key InputRow. How can I do that in Java?
My Java Code is..,
line="1,Kit,23";
final Map<String, String> regexResults = new HashMap<>();
Pattern pattern = Pattern.compile("(.+),(.+),(.+)");
final Matcher matcher = pattern.matcher(line);
if (matcher.find())
{
final String baseKey = "InputRow";
for (int i = 0; i <= matcher.groupCount(); i++) {
final String key = new StringBuilder(baseKey).append(".").append(i).toString();
String value = matcher.group(i);
if (value != null) {
regexResults.put(key, value);
}
}
Now i wants to store the second row also in "regexResults" to process.How it is possible?
Create a class InputRow:
class InputRow {
private int value1;
private String value2;
private int value3;
//...getters and setters
}
and a HashMap<Integer, List<InputRow>>. The hash map key is your row index and you assign all matching rows as a List<InputRow> to the hash map.
For clarification, a HashMap stores one entry for one unique key. Therefore, you cannot assign more than one entry to the same key or else the entry will just be overwritten. So, you need to write a container to cover multiple objects or use an existing like List.
Example for your code
I used both of your text fragments, separated by a newline character, so two lines. This snippet puts two InputRow objects in a list into the HashMap with the key "InputRow". Note, that the matcher group index starts at 1, zero refers to the whole group. Also mind that for simplicity I assumed you created a InputRow(String, String, String) constructor.
String line = "1,Kit,23\n2,Ret,211";
final Map<String, List<InputRow>> regexResults = new HashMap<>();
Pattern pattern = Pattern.compile("(.+),(.+),(.+)");
final Matcher matcher = pattern.matcher(line);
List<InputRow> entry = new ArrayList<>();
while (matcher.find()) {
entry.add(new InputRow(matcher.group(1), matcher.group(2), matcher.group(3)));
}
regexResults.put("InputRow", entry);
It is not possible. A Map can only store one key per definition. The documentation says
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
The only thing you can do is map the key to a List of values. Map<String, List<String>>. Then it could look like this
InputRow.1 --> [1, kit, 23],
InputRow.2 --> [2, Ret, 211]

Read objects content from hashmaps

I need to save pairs (string,object) into a hashmap. Basically I managed to populate the hashmap but I don't know how to access the values stored into memory.
This is my code:
HashMap<String, speedDial> SDs = new HashMap<String, speedDial>();
speedDial sd = new speedDial();
SDs.put(String.valueOf(temp),sd); whre temp is my index and sd my object
Then I fill in data into the sd reading them from an xml file.
When I debug the project with eclypse I can see the values are stored correctly into memory, but I've no idea how to retrive the string values associated to the object, see below the SD object format
class speedDial{
String label, dirN;
speedDial (String l, String dN) {
this.label = l;
this.dirN = dN;
}
}
See the picture below: it highlights the data I'm trying to access!
enter image description here
When I try to access the hashmap and print it's values I only got the last one, I use the following:
for ( int k = 0; k <50; k++) {
speedDial.printSD(SDs.get(String.valueOf(k)));
}
This is my printSD method taken from the speedDial class:
public static void printSD (speedDial SD) {
System.out.println("Dir.N: " + SD.dirN + " Label: " + SD.label);
}
And this is the output for all the 50 iterations, that is the last element I added to the hashmap in another for cycle that reads from a xml file.
Dir.N: 123450 Label: label5
Given a HashMap such as:
SpeedDial speedDial1 = new SpeedDial("test1", "test2");
SpeedDial speedDial2 = new SpeedDial("test3", "test4");
SpeedDial speedDial3 = new SpeedDial("test5", "test6");
HashMap<String, SpeedDial> exampleHashMap = new HashMap<>(3);
exampleHashMap.put("key1", speedDial1);
exampleHashMap.put("key2", speedDial2);
exampleHashMap.put("key3", speedDial3);
You can retrieve the value for a given key like so:
SpeedDial exampleOfGetValue = exampleHashMap.get("key1");
System.out.println(exampleOfGetValue.label);
System.out.println(exampleOfGetValue.dirN);
This outputs:
test1
test2
If you want to retrieve the keys for a given value then you could use something like:
public final <S, T> List<S> getKeysForValue(final HashMap<S, T> hashMap, final T value) {
return hashMap.entrySet()
.stream()
.filter(entry -> entry.getValue().equals(value))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
If you call this function like so:
List<String> exampleOfGetKeys = getKeysForValue(exampleHashMap, speedDial1);
System.out.println(exampleOfGetKeys);
It would output a list of all keys that have this value:
[key1]
The following code will iterate through the map and will store the key and values in two lists.
List<String> keys = new ArrayList();
List<Object> values = new ArrayList();
for (Map.Entry<String, Object> speedDial: SDs.entrySet()) {
Object speedDialValue = speedDial.getValue();
String key= speedDial.getKey();
keys.add(key);
values.add(speedDialValue);
}
To retrieve the String value, typically getters are used as it is recommended to use the private modifier for your class attributes.
public class speedDial{
private String label, dirN;
public speedDial (String l, String dN) {
this.label = l;
this.dirN = dN;
}
public String getLabel(){
return this.label;
}
public String getDirN(){
return this.dirN;
}
}
The you can simply use yourObject.getLabel(); or yourObject.getDirN();
Hope that helps!
SDs.keySet() Gives you the Set of the keys of your HashMap
You can have the list of values using
for (String mapKey : SDs.keySet()) {
System.out.println("key: "+mapKey+" value: "+ SDs.get(mapKey).toString());
}
Yous have to write a toString() fonction for your speedDial

storing multiple values in a map against single key

I have the following file named ght.txt in my c: and it contains the following data
Id|ytr|yts
1|W|T
2|W|T
3|W|T
Now the thing is that positions of this columns (Id|ytr|yts) is also not in order means they can be reshuffled also..for ex
Id|ytr|dgfj|fhfjk|fgrt|yts
or they can be as ..
Id|wer|ytr|weg|yts
so I have done the following way and read them in java as shown below
String[] headers = firstLine.split("|");
int id, Ix, Ixt, count = 0;
for(String header : headers) {
if(header.equals("Id")) {
idIx = count;
}elseif (header.equals("Ix")) {
Ixt = count;
} elseif (header.equals("Ixt")) {
Ixt = count;
}
count++;
}
Now I need to store them in a map in such a way that against id I will get the value of column ytr and yts so in map there should be single key but against that key value could be multiple please advise how to store in map in such a way
Using a Map<Integer,List<String>> sounds like a viable first approach.
As it sound like your value is structured, it might be even better to create a value class to hold this, eg. Map<Integer, YourValueClass> where
class YourValueClass
{
String ix;
String ixt;
// constructor, getters and setters
}
Basically, you should think in terms of classes/objects - don't be in object denial :-)
Cheers,
I'm not quite sure what you mean, but if I get it right, you are looking for a multimap.
You can roll one yourself, as #Anders R. Bystrup suggests.
Or you can use an existing implementation like the Google Collections Multimap.
Don't store one key and multiple values. Instead, you can store a Key and Values as a List.
You can use MultiMap from Guava Library:
MultiMap<String,String> map = ArrayListMultimap.create();
map.put("key","value1");
map.put("key","value2");
By using:
System.out.println(map.get("key");
Prints:
["value1","value2"]
Value Class
class TextValues {
final int id;
final String ix;
final String ixt;
private TextValues(final int id, final String ix, final String ixt){
this.id = id;
this.ix = ix;
this.ixt = ixt;
}
public static TextValues createTextValues(int id, String ix, String ixt) {
return new TextValues(id, ix, ixt);
}
}
Usage:
Map<Integer, TextValues> map = new HashMap<Integer, TextValues>();
map.put(1, TextValues.createTextValues(1, "ix value ", "ixt value"));
public static void main(String[] args) {
Map<String, List<String>> map = new HashMap<String, List<String>>();
List<String> valSetOne = new ArrayList<String>();
valSetOne.add("ABC");
valSetOne.add("BCD");
valSetOne.add("DEF");
List<String> valSetTwo = new ArrayList<String>();
valSetTwo.add("CBA");
valSetTwo.add("DCB");
map.put("FirstKey", valSetOne);
map.put("SecondKey", valSetTwo);
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
String key = entry.getKey();
List<String> values = entry.getValue();
System.out.println("Value of " + key + " is " + values);
}
}
You can use Set or List based on your requirement i.e you need elements in ordered or unordered collection.This is a simple method of having single key with multiple values.

Parse from List<String> Java

I am attempting to parse the value of the elements in a List declared as thus:
List<String> uniqueList = new ArrayList<String>(dupMap.values());
The values are such as this:
a:1-2
b:3-5
but I want one ArrayList with the first number (i.e. 1, 3) and another with the second (i.e. 2, 5). I have this worked out... Sorta:
String delims= "\t"; String delim2= ":"; String delim3= "-";
String splits2[]; String splits3[]; String splits4[];
Map<String,String> dupMap = new TreeMap<String, String>();
List<String> uniqueList = new ArrayList<String>(dupMap.values());
ArrayList<String> parsed2 = new ArrayList<String>();
ArrayList<String> parsed3 = new ArrayList<String>();
ArrayList<String> parsed3two= new ArrayList<String>();
double uniques = uniqueList.size();
for(int a=0;a<uniques;a++){
//this doesn't work like it would for an ArrayList
splits2 = uniqueList.split(delim2) ;
parsed2.add(splits2[1]);
for(int q=0; q<splits2.length; q++){
String change2 = splits2[q];
if(change2.length()>2){
splits3 = change2.split(delim3);
parsed3.add(splits3[0]);
String change3=splits3[q];
if (change3.length()>2){
splits4 = change3.split(delims);
parsed3two.add(splits4[0]);
}
}
}
}
uniqueList.split does not work however and I don't know if there is a similar function for List. Is there any suggestions?
If you know that all of your data is in the form [something]:[num]-[num], you can use a regular expression like this:
Pattern p = Pattern.compile("^([^:]*):([^-]*)-([^-]*)$");
// I assume this holds all the values:
List<String> uniqueList = new ArrayList<String>(dupMap.values());
for (String src : uniqueList) {
Matcher m = p.matcher(src);
if( m.find() && m.groupCount() >= 3) {
String firstValue = m.group(1); // value to left of :
String secondValue = m.group(2); // value between : and -
String thirdValue = m.group(3); // value after -
// assign to arraylists here
}
}
I didn't actually put the code in to add to the specific ArrayLists because I couldn't quite tell from your code which ArrayList was supposed to hold which value.
Edit
Per Code-Guru's comment, an implementation using String.split() would go something like this:
String pattern = "[:\\-]";
// I assume this holds all the values:
List<String> uniqueList = new ArrayList<String>(dupMap.values());
for (String src : uniqueList) {
String[] parts = src.split(pattern);
if (parts.length == 3) {
String firstValue = parts[1]; // value to left of :
String secondValue = parts[2]; // value between : and -
String thirdValue = parts[3]; // value after -
// assign to arraylists here
}
}
Both approaches are pretty much the same in terms of efficiency.
From what I understand of your question, I would proceed as follows:
for each String in uniqueList
parse the string into a character and two integers (probably using a single call to [String.split()](http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String, int))
insert the first integer into an List
insert the second integer into another List
This is in pseudocode. Translating into Java is left as an exercise to the reader.

Categories