Java: Replace in TreeMap - java

I have a Treemap:
TreeMap<String, Integer> map = new TreeMap<String, Integer>();
It counts words that are put in, for example if I insert:
"Hi hello hi"
It prints:
{Hi=2, Hello=1}
I want to replace that "," with a "\n", but I did not understand the methods in Java library. Is this possible to do? And is it possible to convert the whole TreeMap to a String?

When printing the map to the System.out is uses the map's toString function to print the map to the console.
You could either string replace the comma with a newline like this:
String stringRepresentation = map.toString().replace(", ", "\n");
This might however poses problems when your key in the map contains commas.
Or you could create a function to produce the desired string format:
public String mapToMyString(Map<String, Integer> map) {
StringBuilder builder = new StringBuilder("{");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
builder.append(entry.getKey()).append('=').append(entry.getValue()).append('\n');
}
builder.append('}');
return builder.toString();
}
String stringRepresentation = mapToMyString(map);

Guava has a lot of useful methods. Look at Joiner.MapJoiner
Joiner.MapJoiner joiner = Joiner.on('\n').withKeyValueSeparator("=");
System.out.println(joiner.join(map));

Related

Replace a map of values in string

Let's say I have a String text = "abc" and I want to replace a map of values, eg:
a->b
b->c
c->a
How would you go for it?
Because obviously:
map.entrySet().forEach(el -> text = text.replaceAll(el.getKey(), el.getValue()))
won't work, since the second replacement will overwrite also the first replacement (and at the end you won't get bca)
So how would you avoid this "replacement of the previous replacement"?
I saw this answer but I hope in a more concise and naive solution (and hopefully without the use of Apache external packages)
By the way the string can be also more than one character
I came up with this solution with java streams.
String text = "abc";
Map<String, String> replaceMap = new HashMap<>();
replaceMap.put("a", "b");
replaceMap.put("b", "c");
replaceMap.put("c", "a");
System.out.println("Text = " + text);
text = Arrays.stream(text.split("")).map(x -> {
String replacement = replaceMap.get(x);
if (replacement != null) {
return x.replace(x, replacement);
} else {
return x;
}
}).collect(Collectors.joining(""));
System.out.println("Processed Text = " + text);
Output
Text = abc
Processed Text = bca
This is a problem I'd normal handle with regex replacement. The code for that in Java is a bit verbose, but this should work:
String text = "abc";
Map<String, String> map = new HashMap<>();
map.put("a", "b");
map.put("b", "c");
map.put("c", "a");
String regex = map.keySet()
.stream()
.map(s -> Pattern.quote(s))
.collect(Collectors.joining("|"));
String output = Pattern.compile(regex)
.matcher(text)
.replaceAll((m) -> {
String s = m.group();
String r = map.get(s);
return r != null ? r : s;
});
System.out.println(output);
// bca
It's relatively straightforward, if a little verbose because Java. First, create a regex expression that will accept any of the keys in the map (using Pattern.quote() to sanitize them), and then use lambda replacement to pluck the appropriate replacement from the map whenever an instance is found.
The performance-intensive part is just compiling the regex in the first place; the replacement itself should make only one pass through the string.
Should be compatible with Java 1.9+
Java 8 onwards, there is a method called chars that returns an IntStream from which you can get a character corresponding to integer represented by the character and map it using your map.
If your map is String to String map then you could use:
text = text.chars().mapToObj(el -> map.get(String.valueOf((char)el))).
collect(Collectors.joining(""));
if your map is Character to Character then just remove String.valueOf()
text = text.chars().mapToObj(el -> map.get((char)el)).collect(Collectors.joining(""));

Replacing a string in java

I am trying to replace the short form words to normal from a string in java but don't know how to do it in a good way because I can have multiple ('ve 're 'nt) and such. Is it good to use array list and if so how do I achieve that?
What I have tried so far:
public class main {
public static void main(String[] args) {
String s = "We've been doing this for ages. I'm having a difficulty doing this. Thats getting confusing.";
s = s.replaceAll("we've", "we have");
s = s.replaceAll("I'm", "I am");
s = s.replaceAll("that's", "that is");
}
}
Thanks!
You can do it more efficiently using regexes.
First, build a map containing your searches and replacements.
Map<String, String> replacements =
Map.of("we've", "we have", "I'm", "I am" /* etc */);
(or some pre-Java 9 equivalent)
Now, build a regex to match the things you want to replace:
Pattern p = Pattern.compile(
replacements.keySet()
.stream()
.map(Pattern::quote)
.collect(Collectors.joining("|")));
Now, create a Matcher and a StringBuilder in which to accumulate your new string:
Matcher m = p.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String replacement = replacements.get(m.group(0));
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
String newS = sb.toString();
Ideone demo
You could use a Map<String, String>, for example a HashMap where the keys would be the short form to replace and the value the replacement string. Then you could just iterate Map.entrySet() and call the replace method on the string.
Code could be (please note that I have omitted the initial letter - except for I which has to be upper case - to avoid the capitalized problem):
String str = s;
HashMap<String, String> replacements = new HashMap<>();
replacements.put("e've", "e have");
replacements.put("I'm", "I am");
replacements.put("hat's", "hat is");
for (Map.Entry<String, String> entry: replacements.entrySet()) {
str = str.replaceAll(entry.getKey(), entry.getValue());
}
It does not really make sense if it is intended to be used only once, but it could be the base of a method that could be re-used on many strings.
You can use a StringBuilder if you don't want to keep creating new strings all the time:
StringBuilder builder = new StringBuilder("We've been doing this for ages. I'm having a difficulty doing this. That's getting confusing.");
HashMap<String, String> replacements = new HashMap<>();
replacements.put("'ve", " have");
replacements.put("'m", " am");
replacements.put("'s", " is");
// others...
for (Map.Entry<String, String> entry: replacements.entrySet()) {
int index;
while ((index = builder.indexOf(entry.getKey())) != -1) {
builder.replace(index, index + entry.getKey().length(), entry.getValue());
}
}
System.out.println(builder);
Do note that if you are trying to replace all contractions like this, you are unlikely going to succeed 100% as some phrases contract to the same contraction, for example:
That has -> That's
That is -> That's
Also note that some 's don't indicate a contraction:
Mary's <-- how are you handling this?
You can kind of tackle the second problem by looking for more specific sequences like That's instead of just 's, but for the first problem, you will need to somehow understand the context.

Add list values to Treemap in actual order using Java

I have a list of map objects in the following manner
List<Map<String, Object>> insurancePercentageDetails = dao.getinusrancePercentageDetails(age);
This gives me the output in the following way.
[{Age=42, Rate12=0.40, Rate24=0.63, Rate36=0.86, Rate48=1.12, Rate60=1.39, Rate72=1.67, Rate84=1.98, Rate96=2.31, Rate108=3.30, Rate120=3.84, Rate132=4.40, Rate144=5.00, Rate156=5.62, Rate168=6.28, Rate180=6.97, Rate192=7.34, Rate204=7.74, Rate216=8.15, Rate228=8.07, Rate240=8.33}]
My actual target is to have a map in the following sorted order
{12=0.4,24=0.63 ....}
For this I took a static list
private final static List<String> period = new ArrayList<>
(Arrays.asList("Rate12","Rate24","Rate36","Rate48","Rate60","Rate72","Rate84","Rate96","Rate108","Rate120",
"Rate132","Rate144","Rate156","Rate168","Rate180","Rate192","Rate204","Rate216","Rate228","Rate240"));
Then
TreeMap<String, Float> insuranceMatrixMap = new TreeMap<String, Float>();
for(String str : period) {
insuranceMatrixMap.put(str.replaceAll("Rate", ""), ((BigDecimal) (BBUtil.getInstance().getValue(insurancePercentageDetails, str))).floatValue());
}
This gives me the output
{108=3.3, 12=0.4, 120=3.84, 132=4.4, 144=5.0, 156=5.62, 168=6.28, 180=6.97, 192=7.34, 204=7.74, 216=8.15, 228=8.07, 24=0.63, 240=8.33, 36=0.86, 48=1.12, 60=1.39, 72=1.67, 84=1.98, 96=2.31}
Not in sorted order.
TreeMap should keep the keys in the sorted order, Isn't it?
Am I missing anything here?
You are right that TreeMap will sort based on the keys.
But in your case the Key is String rather than Integer.
And the result is sorted based on the String Value, i.e.
"108".compareTo("12") will be negative.
The String comparison is based on the Unicode value of each character.
You have to use TreeMap<Integer, Float> if you want to sort on the Integer value.
you can sort it before loop same this :
Collections.sort(period, new Comparator<String>() {
#Override
public int compare(final String o1, final String o2) {
return Integer.valueOf(o1.replaceAll("Rate", ""))
.compareTo(Integer.valueOf(o2.replaceAll("Rate", "")));
}
});

Java String array parsing and getting data

String input data is
{phone=333-333-3333, pr_specialist_email=null, sic_code=2391, status=ACTIVE, address1=E.BALL Drive, fax=333-888-3315, naics_code=325220, client_id=862222, bus_name=ENTERPRISES, address2=null, contact=BYRON BUEGE}
Key and values will increase in the array.
I want to get the value for each key ie myString.get("phone") should return 333-333-3333
I am using Java 1.7, is there any tools I can use this to parse the data and get the values.
Some of my input is having values like,
{phone=000000002,Desc="Light PROPERTITES, LCC", Address1="C/O ABC RICHARD",Address2="6508 THOUSAND OAKS BLVD.,",Adress3="SUITE 1120",city=MEMPHIS,state=TN,name=,dob=,DNE=,}
Comma separator doesn't work here
Here is a simple function that will do exacly what you want. It takes your string as an input and returns a Hashmap containing all the keys and values.
private HashMap<String, String> getKeyValueMap(String str) {
// Trim the curly ({}) brackets
str = str.trim().substring(1, str.length() - 1);
// Split all the key-values tuples
String[] split = str.split(",");
String[] keyValue;
HashMap<String, String> map = new HashMap<String, String>();
for (String tuple : split) {
// Seperate the key from the value and put them in the HashMap
keyValue = tuple.split("=");
map.put(keyValue[0].trim(), keyValue[1].trim());
}
// Return the HashMap with all the key-value combinations
return map;
}
Note: This will not work if there's ever a '=' or ',' character in any of the key names or values.
To get any value, all you have to do is:
HashMap<String, String> map = getKeyValueMap(...);
String value = map.get(key);
You can write a simple parser yourself. I'll exclude error checking in this code for brevity.
You should first remove the { and } characters, then split by ', ' and split each resulting string by =. At last add the results into a map.
String input = ...;
Map<String, String> map = new HashMap<>();
input = input.substring(1, input.length() - 1);
String elements[] = input.split(", ");
for(String elem : elements)
{
String values[] = elem.split("=");
map.put(values[0].trim(), values[1].trim());
}
Then, to retrieve a value, just do
String value = map.get("YOURKEY");
You can use "Google Core Libraries for Java API" MapSplitter to do your job.
First remove the curly braces using substring method and use the below code to do your job.
Map<String, String> splitKeyValues = Splitter.on(",")
.omitEmptyStrings()
.trimResults()
.withKeyValueSeparator("=")
.split(stringToSplit);

Java String not replacing with hashmap values

for (Entry<String, String> entry : map.entrySet()) {
String delimiter = "**";
result = result.replace(delimiter + entry.getKey() + delimiter, entry.getValue());
}
result is my string to be replaced by hashmap values.
Here string (result variable) is returning as itself not replacing any value.
Please any one have suggestions ?
From comment
My hashmap contains,
HashMap<String, String> map = new HashMap<String, String>();
map.put("Rid", serviceBooking.getId().toString());
map.put("Rname", customer.getName());
map.put("Rnic", "");
The algorithm OK Here's a working, executable example:
// sample input
String input = "abcd **Rid** efgh";
// a small map
Map<String, String> map = new HashMap<String, String>();
map.put("Rid","VALUE");
// the loop that replaces the **Rid** substring
for (Map.Entry<String,String> entry:map.entrySet()){
input = input.replace("**"+entry.getKey()+"**", entry.getValue());
System.out.println(input);
}
It prints
abcd VALUE efgh
Either your HashMap is empty, or the original string doesn't contain anything corresponding to the keys in the map, or you wrote two asterisks where you meant one, or you didn't escape it/them when you needed to, or ...
Impossible to improve on that without seeing the original string and the contents of the map.

Categories