This question already has answers here:
How to convert map to url query string?
(20 answers)
Closed 4 years ago.
I want to create util method which converts HashMap into long String with keys and values:
HashMap<String, String> map = new LinkedhashMap<>();
map.put("first_key", "first_value");
map.put("second_key", "second_value");
I need to get this end result:
first_key=first_value&second_key=second_value
You can use streams:
String result = map.entrySet().stream()
.map(e -> e.getKey() + "=" + e.getValue())
.collect(Collectors.joining("&"));
Note: You should probably use an url encoding. First create a helper method like this:
public static String encode(String s){
try{
return java.net.URLEncoder.encode(s, "UTF-8");
} catch(UnsupportedEncodingException e){
throw new IllegalStateException(e);
}
}
And then use that inside of your stream to encode the key and value:
String result = map.entrySet().stream()
.map(e -> encode(e.getKey()) + "=" + encode(e.getValue()))
.collect(Collectors.joining("&"));
Try this:
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : map.entrySet()) {
sb.append(entry.getKey());
sb.append('=');
sb.append(entry.getValue());
sb.append('&');
}
sb.deleteCharAt(sb.length() - 1);
String result = sb.toString();
map.toString().replace(",","&")
The output Map::toString is not much different from the output you want. Compare:
{first_key=first_value, second_key=second_value}
first_key=first_value&second_key=second_value
Just perform the right character replacement:
map.toString().replaceAll("[{ }]", "").replace(",","&")
"[{ }]" is regex matching all the brackets {} and the space - those to be removed (replaced with "").
, to be replaced with & character.
Related
This is my map:
Map<String, Object> params = new HashMap<>();
params.put("topicRef", "update-123456-78925-new-u1z1w3");
params.put("parentRef", "update-123456-78925-new-u1z1w3");
Script script = new Script(ScriptType.INLINE, "painless",
String.format("ctx._source.parentRef = params.parentRef; ctx._source.topicRef = params.topicRef"),
params);
request.setScript(script);
I want to convert my map into a string but I would like to change the pattern for e.g.:
"ctx._source.key = value;ctx._source.key = value"
I want to add to key value a prefix ctx._source.key and a suffix " =" (space and equal), then I would like to separate each entry with a semicolon.
String formattedMap = params.entrySet().
stream()
.map(e -> "ctx._source." + e.getKey() + " = " + e.getValue())
.collect(Collectors.joining(","));
Try something like this:
Map<String, String> yourMap = /*...*/;
StringBuilder bob = new StringBuilder();
yourMap.forEach((key, value) -> bob.append(key).append("=").append(value).append(";"));
String result = bob.toString();
If necessary you could remove the last ; on result via String.concat().
You could stream your Map's entries, then use the map operation to map each entry to the formatted String and ultimately join each element with the collect(Collectors.joining(";")) operation.
Map<String, Object> params = new HashMap<>();
params.put("topicRef", "update-123456-78925-new-u1z1w3");
params.put("parentRef", "update-123456-78925-new-u1z1w3");
String result = params.entrySet().stream()
.map(entry -> String.format("%s%s%s%s", "ctx._source.", entry.getKey(), " =", entry.getValue()))
.collect(Collectors.joining(";"));
System.out.println(result);
Here is a link to test the code
https://www.jdoodle.com/iembed/v0/rrK
Output
String result = params.entrySet()
.stream()
.map(x -> "ctx._source." + x.getKey() + " = " + x.getValue())
.reduce((x, y) -> x + ";" + y).get();
I want to convert a Stream of a Map<> into a String, to append it to a textArea. I tried some methods, the last with StringBuilder, but they don't work.
public <K, V extends Comparable<? super V>> String sortByAscendentValue(Map<K, V> map, int maxSize) {
StringBuilder sBuilder = new StringBuilder();
Stream<Map.Entry<K,V>> sorted =
map.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
BufferedReader br = new BufferedReader(new InputStreamReader((InputStream) sorted));
String read;
try {
while ((read=br.readLine()) != null) {
//System.out.println(read);
sBuilder.append(read);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sorted.limit(maxSize).forEach(System.out::println);
return sBuilder.toString();
}
You can collect the entries into a single String as follows:
String sorted =
map.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.map(e-> e.getKey().toString() + "=" + e.getValue().toString())
.collect(Collectors.joining (","));
Consider slight change to #Eran's code, with regard to the fact that HashMap.Entry.toString() already does joining by = for you:
String sorted =
map.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.map(Objects::toString)
.collect(Collectors.joining(","));
It is easy to do this, you can use the Steams API to do this. First, you map each entry in the map to a single string - the concatenated string of key and value. Once you have that, you can simply use the reduce() method or collect() method to do it.
Code snippet using 'reduce()' method will look something like this:
Map<String, String> map = new HashMap<>();
map.put("sam1", "sam1");
map.put("sam2", "sam2");
String concatString = map.entrySet()
.stream()
.map(element-> element.getKey().toString() + " : " + element.getValue().toString())
.reduce("", (str1,str2) -> str1 + " , " + str2).substring(3);
System.out.println(concatString);
This will give you the following output:
sam2 : sam2 , sam1 : sam1
You can also use the collect()' method instead ofreduce()` method. It will look something like this:
String concatString = map.entrySet()
.stream()
.map(element-> element.getKey().toString() + " : " + element.getValue().toString())
.collect(Collectors.reducing("", (str1,str2) -> str1 + " , " + str2)).substring(3);
Both methods give the same output.
I am new to Java. I have a problem that, I need to Implement the decode(String) method that decodes a String to a corresponding Map. In the assignment, the requirements are like this,
Empty keys and values are allowed, but the equals sign must be present (e.g. "=value", "key=").
If the key or value is empty, empty String should be returned.
If the given String is empty, an empty Map should be returned.
If the given String is null, null should be returned.
Sample Input: one=1&two=2
Should return a Map containing {"one": "1", "two": "2"}
Map<String, String> map = new HashMap<>();
map.put("One", "1");
map.put("Two", "2");
map.put("", "");
map.put("Key", "");
map.put("", "Value");
Set<String> keys = map.keySet();
for(String key : keys) {
System.out.print("\"" + key + "\"" + ":" + "\"" + map.get(key) + "\"");
}
My piece of code is giving output as required, But I have implemented this in the main method with Map<K, V> interface, while I need to write code that takes String as a parameter and decodes to Map.
Thanks
One solution could be:
public Map<String, String> parseMap(String mapString) {
if (mapString == null || mapString.isEmpty()) {
return Collections.emptyMap();
}
return Arrays.stream(mapString.split("&"))
.map(this::splitParam)
.collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));
}
public AbstractMap.SimpleEntry<String, String> splitParam(String it) {
final int idx = it.indexOf("=");
final String key = it.substring(0, idx);
final String value = it.substring(idx + 1);
return new AbstractMap.SimpleEntry<>(key, value);
}
usage
String inputString = "one=1&two=2";
Map<String, String> map = parseMap(inputString);
//your code to print the map again
Set<String> keys = map.keySet();
for(String key : keys) {
System.out.print("\"" + key + "\"" + ":" + "\"" + map.get(key) + "\"");
}
try this in your editor, just 4 lines :)
String input = "one=1&two=2";
String[] kvs = input.split("&");
Map<String, String> hashMap = Stream.of(kvs)
.collect(Collectors.toMap(item -> item.split("=")[0],
item -> item.split("=")[1]));
hashMap.forEach((k, v) -> System.out.println(k + ":" + v));
I am getting a response which has key value pairs separated by :
USER: 0xbb492894B403BF08e9181e42B07f76814b10FEdc
IP: 10.0.2.6
NETMASK: 255.255.0.0
SUPERNODE: tlcsupernode.ddns.net
PORT: 5000
COMMUNITY: tlcnet
PSK: mysecret
MAC: 00:02:ff:00:02:06
To parse and store them, I am using the below code:
Map<String, String> map = new HashMap<String, String>();
String[] parts = response.trim().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));
Log.d("Testing", " "+s + " is " + map.get(s));
}
But as the MAC has multiple times : separator, I am not able to parse it properly.
I got the help from the below link:
Split string into key-value pairs
Using Java 8 streams, you can do it as a one liner.
String resp = "USER: 0xbb492894B403BF08e9181e42B07f76814b10FEdc\n" +
"IP: 10.0.2.6\n" +
"NETMASK: 255.255.0.0\n" +
"SUPERNODE: tlcsupernode.ddns.net\n" +
"PORT: 5000\n" +
"COMMUNITY: tlcnet\n" +
"PSK: mysecret\n" +
"MAC: 00:02:ff:00:02:06";
Map<String, String> map = Arrays.asList(resp.split("\\R")).stream().map(x -> x.split(":", 2)).collect(Collectors.toMap(x -> x[0], x -> x[1].trim()));
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(String.format("Key: %s, Value: %s", entry.getKey(), entry.getValue()));
}
Prints,
Key: SUPERNODE, Value: tlcsupernode.ddns.net
Key: NETMASK, Value: 255.255.0.0
Key: COMMUNITY, Value: tlcnet
Key: PORT, Value: 5000
Key: IP, Value: 10.0.2.6
Key: PSK, Value: mysecret
Key: USER, Value: 0xbb492894B403BF08e9181e42B07f76814b10FEdc
Key: MAC, Value: 00:02:ff:00:02:06
Here, \\R (matches any type of newline) splits your response string with newline which further gets split using : with second parameter as 2 to split the string to get max two values, and finally gets collected as Map using Collectors.toMap
Edit:
For older version of Java, you can use a simple for loop,
String resp = "USER: 0xbb492894B403BF08e9181e42B07f76814b10FEdc\n" + "IP: 10.0.2.6\n" + "NETMASK: 255.255.0.0\n"
+ "SUPERNODE: tlcsupernode.ddns.net\n" + "PORT: 5000\n" + "COMMUNITY: tlcnet\n" + "PSK: mysecret\n"
+ "MAC: 00:02:ff:00:02:06";
Map<String, String> map = new HashMap<>();
for (String line : resp.split("\\R")) {
String[] keyValue = line.split(":", 2);
map.put(keyValue[0], keyValue[1]);
}
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(String.format("Key: %s, Value: %s", entry.getKey(), entry.getValue()));
}
Instead of
String[] parts = response.trim().split(":");
Do this:
String[] parts = response.trim().split(":", 2);
That 2 at the end will force the string to be split into only two substrings. Using no additional parameter like you're doing currently means "split into an unlimited number of substrings".
Also, you should trim the keys and values before storing them in case there are spaces around the initial ':'
One caveat: This assumes that the additional ':' characters will always occur in the value, and not in the key.
See here for more details.
You can just change your split regex to :\\s|\\n. With this the code you are using should work as expected.
Another solution is to split by \\R first and handle each line separately. For this you either can use line.split(":", 2) or line.split(":\\s"). If you need a more flexible solution you can use a regex to process each line.
Pattern pattern = Pattern.compile("(?<key>.+):\\s+(?<value>.+)");
Map<String, String> map = new HashMap<>();
for (String line : response.split("\\R")) {
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
map.put(matcher.group("key"), matcher.group("value"));
}
}
For Java 8 and above you can use the Stream API:
Pattern pattern = Pattern.compile("(?<key>.+):\\s+(?<value>.+)");
Map<String, String> map2 = Arrays.stream(response.split("\\R"))
.map(pattern::matcher)
.filter(Matcher::find)
.collect(Collectors.toMap(m -> m.group("key"), m -> m.group("value")));
The combination of colon followed by whitespace does seem to be unique, at least in the sample data you showed us. So, try splitting on that:
String[] parts = response.split(":\\s+");
map.put(parts[0], parts[1]);
This question already has answers here:
Most efficient way to use replace multiple words in a string [duplicate]
(4 answers)
Closed 5 years ago.
I want to do something like this: Replace all ck with k and all dd with wr and all f with m and 10 more replacements like this.
I can do it with replace("ck","k").replace("dd","wr")and so on, but it seams silly and it is slow. Is there any function in java that does something like this?
for example replace(string,stringArray1, stringArray2);
Use an appendReplacement loop.
Here is a general purpose way to do it:
private static String replace(String input, Map<String, String> mappings) {
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile(toRegex(mappings.keySet())).matcher(input);
while (m.find())
m.appendReplacement(buf, Matcher.quoteReplacement(mappings.get(m.group())));
return m.appendTail(buf).toString();
}
private static String toRegex(Collection<String> keys) {
return keys.stream().map(Pattern::quote).collect(Collectors.joining("|"));
}
If you're not using Java 8+, the second method would be:
private static String toRegex(Collection<String> keys) {
StringBuilder regex = new StringBuilder();
for (String key : keys) {
if (regex.length() != 0)
regex.append("|");
regex.append(Pattern.quote(key));
}
return regex.toString();
}
Test code
Map<String, String> mappings = new HashMap<>();
mappings.put("ck","k");
mappings.put("dd","wr");
mappings.put("f", "m");
System.out.println(replace("odd flock", mappings)); // prints: owr mlok
See IDEONE for running version.
Map<String, String> replacementMap = new HashMap<String, String>();
replacementMap.put("ck", "k");
replacementMap.put("dd", "wr");
replacementMap.put("f", "m");
// ...
String resultStr = "Abck fdddk wr fmck"; // whatever string to process
StringBuilder builder = new StringBuilder(resultStr); // wrap it in builder
Iterator<String> iterator = replacementMap.keySet().iterator();
while (iterator.hasNext()) {
String strToReplace = iterator.next();
replaceAll(builder, strToReplace, replacementMap.get(strToReplace));
}
System.out.println("Result is: " + builder.toString());
public static void replaceAll(StringBuilder builder, String from, String to) {
int index = builder.indexOf(from);
while (index != -1) {
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
}
The replaceAll() method was borrowed from this Jon Skeet's answer
Alternative to replaceAll() int his example is to use apache commons library, there is StrBuilder class which provides replaceAll() method. see this answer