Unless Splitter is doing any magic, the getTokenizeString method is obsolete here. You can perform the entire processing as a single operation:
Map<String,String> map = Pattern.compile("\\s*-\\s*")
.splitAsStream(responseString.trim())
.map(s -> s.split("~", 2))
.collect(Collectors.toMap(a -> a[0], a -> a.length>1? a[1]: ""));
By using the regular expression \s*-\s* as separator, you are considering white-space as part of the separator, hence implicitly trimming the entries. There’s only one initial trim operation before processing the entries, to ensure that there is no white-space before the first or after the last entry.
Then, simply split the entries in a map step before collecting into a Map.
Unless Splitter is doing any magic, the getTokenizeString method is obsolete here. You can perform the entire processing as a single operation:
Map<String,String> map = Pattern.compile("\\s*-\\s*")
.splitAsStream(responseString.trim())
.map(s -> s.split("~", 2))
.collect(Collectors.toMap(a -> a[0], a -> a.length>1? a[1]: ""));
By using the regular expression \s*-\s* as separator, you are considering white-space as part of the separator, hence implicitly trimming the entries. There’s only one initial trim operation before processing the entries, to ensure that there is no white-space before the first or after the last entry.
Then, simply split the entries in a map step before collecting into a Map.
First of all, you don't have to split the same String twice.
Second of all, check the length of the array to determine if a value is present for a given key.
HashMap<String, String> map=
list.stream()
.map(s -> s.split("~"))
.collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));
This is assuming you want to put the key with a null value if a key has no corresponding value.
Or you can skip the list variable :
HashMap<String, String> map1 =
MyClass.getTokenizeString(responseString, "-")
.stream()
.map(s -> s.split("~"))
.collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1] : ""));
You can use the following snippet for this:
Map<String, Map<String, String>> result = Arrays.stream(samp.split(","))
.map(i -> i.split("-"))
.collect(Collectors.groupingBy(a -> a[0], Collectors.toMap(a -> a[1], a -> a[2])));
First it creates a Stream of your items, which are mapped to a stream of arrays, containing the subitems. At the end you collect all by using group by on the first subitem and create an inner map with the second value as key and the last one as value.
The result is:
{101={1=5, 2=4}, 102={1=5, 2=5, 3=5}, 103={1=4}}
Map<String, Map<String, String>> map = Arrays.stream(samp.split(","))
.map(s -> s.split("-"))
.collect(Collectors.toMap(
o -> o[0],
o -> Map.of(o[1], o[2]),
(m1, m2) -> Stream.concat(m1.entrySet().stream(), m2.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))));
Map.of is from Java 9, you can use AbstractMap.SimpleEntry if you are on Java 8.
Samuel's answer is better though, much concise.
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);
}
}
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.
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}]
Based on tags you are looking for stream solutions. Here is one
String text = "id1:name1,id2:name1,id3:name2,id4:name2,id5:name2";
Map<String, List<String>> map = Arrays
.stream(text.split(","))
.map(pair -> pair.split(":"))
.collect(Collectors.groupingBy(
pair -> pair[1],
Collectors.mapping(e -> e[0], Collectors.toList())
)
);
System.out.println(map);
Output: {name2=[id3, id4, id5], name1=[id1, id2]}
You could use following code:
public static void main(String[] args) {
String input = "id1:name1,id2:name1,id3:name2,id4:name2,id5:name2";
String[] pairs = input.split(",");
Map<String, String> result = Stream.of(pairs)
.map(pair -> pair.split(":"))
.collect(Collectors.toMap(
splittedPair -> splittedPair[1], // to key function (extracts name)
splittedPair -> splittedPair[0], // to value function ( extracts id)
(id1, id2) -> id1 + "," + id2)); // in case of same name merges id
System.out.println(result);
}
The output is following: {name2=id3,id4,id5, name1=id1,id2}
If you need as a result Map<String, List<String>> you can use following collector:
Map<String, List<String>> result = Stream.of(pairs)
.map(pair -> pair.split(":"))
.collect(Collectors.toMap(
splittedPair -> splittedPair[1],
splittedPair -> {
List<String> ids = new ArrayList<>();
ids.add(splittedPair[0]);
return ids;
},
(idList1, idList2) -> {
idList1.addAll(idList2);
return idList1;
}));
You should use a Collectors::mapping to map the array to an element.
String flString = "view1:filedname11,view1:filedname12,view2:fieldname21";
Map<String, List<String>> map = Pattern.compile(",")
.splitAsStream(flString)
.map(a -> a.split(":"))
.collect(
Collectors.groupingBy(a -> a[0],
Collectors.mapping(a -> a[1], Collectors.toList())
)
);
map.entrySet().forEach(System.out::println);
Output
view1=[filedname11, filedname12]
view2=[fieldname21]
You can use Collectors#toMap(keyMapper,valueMapper,mergeFunction) method as follows:
String flString = "view1:filedname11,view1:filedname12,view2:fieldname21";
Map<String, Set<String>> map = Arrays
.stream(flString.split(","))
.map(str -> str.split(":"))
.collect(Collectors.toMap(
arr -> arr[0],
arr -> new HashSet<>(Set.of(arr[1])),
(s1, s2) -> {
s1.addAll(s2);
return s1;
}));
System.out.println(map);
// {view1=[filedname11, filedname12], view2=[fieldname21]}
You could use a loop to iterate over the key value pairs and put them into the map:
String[] cookieArr = cookies.split(";");
for(String cookieString : cookieArr){
String[] pair = cookieString.split("=");
if(pair.length < 2){
continue;
}
map.put(pair[0], pair[1]);
}
The if is only there to prevent ArrayIndexOutOfBounds expcetions if cookie string is malformed
an alternativ would be using a stream:
Arrays.stream(cookies.split(";")).forEach(cookieStr -> map.put(cookieStr.split("=")[0], cookieStr.split("=")[1]));
As mentioned by @WJS in the comment, you could use map.putIfAbsent(key, vlaue) instead of map.put(key, value) to prevent overriding of values. But in case of cookies it could be a desired behavior to overwrite the old value with the new.
You could do it like this. It presumes your format is consistent.
- first splits each k/v pair on ";"
- the splits on "=" into key and value.
- and adds to map.
- if duplicate keys show up, the first one encountered takes precedence (if you want the latest value for a duplicate key then use
(a, b)-> bas the merge lambda.)
String cookies = "i=lol;haha=noice;df3=ddtb";
Map<String, String> map = Arrays.stream(cookies.split(";"))
.map(str -> str.split("=")).collect(Collectors
.toMap(a -> a[0], a->a[1], (a, b) -> a));
map.entrySet().forEach(System.out::println);
Prints
df3=ddtb
haha=noice
i=lol
A simpler approach is to just use split with standard arrays.
String[] keyValues = currentString.split("=", 2);
String[] keys = keyValues[0].split("-");
String[] values = keyValues[1].split("-", keys.length);
Map<String, String> map = IntStream.range(0, keys.length).boxed()
.collect(Collectors.toMap(i -> keys[i], i -> values[i]));
There's no error checking in this but hopefully it'll give you the general idea.
As shown in this answer, a plain array based operation may be much simpler here.
But if you insist on a Stream solution, it may look like
Map<String,String> mapVal= Stream.of(currentString)
.map(s0 -> Arrays.stream(s0.split("\\s*=\\s*", 2))
.map(s1 -> s1.split("-")).toArray(String[][]::new))
.flatMap(a -> IntStream.range(0, a[0].length)
.mapToObj(i -> new String[]{ a[0][i], i < a[1].length? a[1][i]: "" }))
.collect(Collectors.toMap(a -> a[0], a -> a[1]));