import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.StringTokenizer;
public class shift {
#SuppressWarnings("unchecked")
public static void main(String args[])
{
String speech = "Sentence:NounPhrase VerbPhrase:NounPhrase :Art Noun:VerbPhrase : Verb | Adverb Verb: Art : the | a : Verb :jumps | sings |: Noun:dog | cat | ";
HashMap<String, String> hashmap = new HashMap<String, String>();
String a;
StringTokenizer st = new StringTokenizer(speech,":");
while (st.hasMoreTokens()) {
String key=st.nextToken().trim();
String value=st.nextToken().trim();
StringTokenizer st1 = new StringTokenizer(value,"|");
while (st1.hasMoreTokens()) {
a=st1.nextToken().trim();
hashmap.put(key, a);
}
}
Set set = hashmap.entrySet();
Iterator ia = set.iterator();
while(ia.hasNext()) {
Map.Entry me = (Map.Entry)ia.next();
System.out.println(me.getKey()+"->"+me.getValue());
}
}
}
the output is
Noun->cat
NounPhrase->Art Noun
Art->a
Sentence->NounPhrase VerbPhrase
Verb->sings
VerbPhrase->Adverb Verb
this code is missing some values to return such as the the jumps etc are not show
Not sure I get your question fully, but keep in mind that a HashMap can only store one value per key.
If you want to store multiple verbs for the key "Verb", then you would have to declare the map using something like:
HashMap<String, Set<String>> hashmap = new HashMap<String, Set<String>>();
and store the words mapped to by "Verb" in a set.
Here is a brushed up (working) version of the code:
import java.util.*;
public class Shift {
public static void main(String args[]) {
String speech = "Sentence:NounPhrase VerbPhrase:NounPhrase :Art " +
"Noun:VerbPhrase : Verb | Adverb Verb: Art : the | " +
"a : Verb :jumps | sings |: Noun:dog | cat | ";
Map<String, Set<String>> hashmap = new HashMap<String, Set<String>>();
StringTokenizer st = new StringTokenizer(speech, ":");
while (st.hasMoreTokens()) {
String key = st.nextToken().trim();
String value = st.nextToken().trim();
StringTokenizer st1 = new StringTokenizer(value, "|");
while (st1.hasMoreTokens()) {
String a = st1.nextToken().trim();
if (!hashmap.containsKey(key))
hashmap.put(key, new HashSet<String>());
hashmap.get(key).add(a);
}
}
for (String key : hashmap.keySet())
System.out.printf("%s -> %s%n", key, hashmap.get(key));
}
}
You're overwriting the existing value when you call hashmap.put(key, a), since you're assigning a value to a key that already has a value.
Related
I have a method that returns some kind of string. I want to store the individual words in a HashMap with their number of occurrences?
public static void main(String[] args) {
String s = "{link:hagdjh, matrics:[{name:apple, value:1},{name:jeeva, value:2},{name:abc, value:0}]}";
String[] strs = s.split("matrics");
System.out.println("Substrings length:" + strs.length);
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);
}
}
For eg, I have a string- "{link:https://www.google.co.in/, matrics:[{name:apple, value:1},{name:graph, value:2},{name:abc, value:0}]}";
Now my hashmap should look like
apple = 1
graph = 2
abc = 0
How should I proceed?
I know how to use HashMaps. My problem, in this case, is that I don't know how to parse through the given string and store the words with their number of occurrences.
String regex = "\\{name:(.*), value:(\\d+)\\}";
HashMap<String, Integer> link = new HashMap<>();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(s);
while (matcher.find()){
String found = matcher.group(1);
String number = matcher.group(2);
link.put(found, Integer.parseInt(number));
}
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<String, Integer>();
Pattern pattern = Pattern.compile("matrics:\\[\\{(.*?)\\]\\}");
Matcher matcher = pattern
.matcher("{link:hagdjh, matrics:[{name:apple, value:1},{name:jeeva, value:2},{name:abc, value:0}]}");
String data = "";
if (matcher.find()) {
data = matcher.group();
}
List<String> records = new ArrayList<String>();
pattern = Pattern.compile("(?<=\\{).+?(?=\\})");
matcher = pattern.matcher(data);
while (matcher.find()) {
records.add(matcher.group());
}
for (String s : records) {
String[] parts = s.split(", ");
map.put(parts[0].substring(parts[0].indexOf(":") + 1),
Integer.parseInt(parts[1].substring(parts[1].indexOf(":") + 1)));
}
map.entrySet().forEach(entry -> {
System.out.println(entry.getKey() + " = " + entry.getValue());
});
}
}
Output:
apple = 1
jeeva = 2
abc = 0
It appeares that your data is in JSON format.
If it is guaranteed to be in JSON format, you can parse it using JSON parsing library and than analyze the matrics data in a convinient way (code follows).
If the data is not guaranteed to be in JSON format, you can use REGEX to help you parse it, as in Reza soumi's answer.
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.HashMap;
String s = "{link:hagdjh, matrics:[{name:apple, value:1},{name:jeeva, value:2},{name:abc, value:0}]}";
JSONObject obj = new JSONObject(s);
JSONArray matrics = obj.getJSONArray("matrics");
System.out.println(matrics);
HashMap<String, Integer> matricsHashMap = new HashMap<String, Integer>();
for (int i=0;i < matrics.length();i++){
JSONObject matric = matrics.getJSONObject(i);
System.out.println("Adding matric: " + matric + " to hash map");
String matricName = matric.getString("name");
Integer matricValue = Integer.valueOf(matric.getInt("value"));
matricsHashMap.put(matricName, matricValue);
}
System.out.println(matricsHashMap);
Try this:
import static java.lang.System.err;
import static java.lang.System.out;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toMap;
/**
* Counting the words in a String.
*/
public class CountWordsInString
{
/*-----------*\
====** Constants **========================================================
\*-----------*/
/**
* An empty array of {#code ${type_name}} objects.
*/
public static final String INPUT = "{link:https://www.google.co.in/, matrics:[{name:apple, value:1},{name:graph, value:2},{name:abc, value:0}]}";
/*---------*\
====** Methods **==========================================================
\*---------*/
/**
* The program entry point.
*
* #param args The command line arguments.
*/
public static void main( final String... args )
{
try
{
final var result = stream( INPUT.split( "\\W+" ) )
.filter( s -> !s.isBlank() )
.filter( s -> !s.matches( "\\d*" ) )
.collect( groupingBy( s -> s ) )
.entrySet()
.stream()
.collect( toMap( k -> k.getKey(), v -> Long.valueOf( v.getValue().size() ) ) );
out.println( result.getClass() );
for( final var entry : result.entrySet() )
{
out.printf( "'%s' occurred %d times%n", entry.getKey(), entry.getValue() );
}
}
catch( final Throwable t )
{
//---* Handle any previously unhandled exceptions *----------------
t.printStackTrace( err );
}
} // main()
}
// class CountWordsInString
Confessed, not the most obvious solution, but I wanted to have some fun with it, too.
The INPUT.split( "\\W+" ) gives you the words in the string, but also numbers and an 'empty' word at the beginning.
The 'empty' word is eliminated with the first filter() statement, the numbers go with the second.
The first collect( groupingBy() ) gives you a HashMap<String,List<String>>, so I had to convert that to a HashMap<String,Long> in the following steps (basically with the second collect( groupingBy() )).
May be there is a more efficient solution, or one that is more elegant, or even one that is both, more efficient and more elegant … but it works as expected, and I had some fun with it.
The output is:
class java.util.HashMap
'apple' occurred 1 times
'matrics' occurred 1 times
'abc' occurred 1 times
'in' occurred 1 times
'www' occurred 1 times
'name' occurred 3 times
'link' occurred 1 times
'google' occurred 1 times
'https' occurred 1 times
'co' occurred 1 times
'value' occurred 3 times
'graph' occurred 1 times
The goal is to write a text message abbreviation expander program that takes a string and checks for common abbreviations like LOL, IDK, etc. and replace them with the full length sentence, laugh out loud, I don't know, etc.
import java.util.HashMap;
import java.util.Scanner;
public class TextMsgExpander {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
System.out.println("Enter text: ");
String userInput = scnr.nextLine();
System.out.println("You entered: " + userInput);
// Create new instance of Hash Map
HashMap<String, String> map = new HashMap<String, String>();
//Key value pairs
map.put("LOL", "laugh out loud");
map.put("IDK", "I don't know");
map.put("BFF", "best friend forever");
map.put("TTYL", "talk to you later");
map.put("JK", "just kidding");
map.put("TMI", "too much information");
map.put("IMHO", "in my humble opinion");
//Access points
String LOL = map.get("LOL");
String IDK = map.get("IDK");
String BFF = map.get("BFF");
String TTYL = map.get("TTYL");
String JK = map.get("JK");
String TMI = map.get("TMI");
String IMHO = map.get("IMHO");
System.out.println(TMI);
// While user input contains any of the keys, replace keys with
// values.
return;
}
}
You can instead iterate(loop) over the complete set of keys and look for them in the userInput, if they are present replace them with the respective value from the map as :
for (Map.Entry<String, String> entry : map.entrySet()) {
if (userInput.contains(entry.getKey())) {
userInput = userInput.replaceAll(entry.getKey(), entry.getValue());
}
}
System.out.println("Converted string - " + userInput);
As part of my HOMEWORK, I am trying to read a file made up of car models and output the total of each to the console.
I have achieved this so far by using a Map with the model name as the key and the counter as the value.
Although, now I want to only output models that are added to a Set.
So, if Fiat was in the file, it wouldnt be used as it is not in the allowable Set.
Hopefully that makes sense and help is appreciated.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
public class Test
{
public static void main(String[] args) throws FileNotFoundException
{
TreeMap<String, Integer> map = new TreeMap<String, Integer>();
Set<String> fruit = new TreeSet<String>();
fruit.add("BMW");
fruit.add("Mercedes");
fruit.add("Ford");
fruit.add("Nissan");
fruit.add("Tesla");
File inputFile = new File("input.txt");
Scanner in = new Scanner(inputFile);
while (in.hasNext())
{
String word = in.next();
if (map.containsKey(word))
{
int count = map.get(word) + 1;
map.put(word, count);
}
else
{
map.put(word, 1);
}
}
in.close();
for (Map.Entry<String, Integer> entry : map.entrySet())
{
System.out.println(entry);
}
}
}
You could just iterate through your set and then invoke the map's "get" method.
e.g.
for ( String car : fruit ) {
Integer value = map.get( car );
if ( value != null ) {
System.out.println( value );
}
}
If the result is not null then print it to the console, otherwise, look for the next one.
try this,
TreeMap<String, Integer> map = new TreeMap<String, Integer>();
Set<String> fruit = new TreeSet<String>();
fruit.add("BMW");
fruit.add("Mercedes");
fruit.add("Ford");
fruit.add("Nissan");
fruit.add("Tesla");
map.put("BMW", 2);
map.put("Ford", 2);
map.put("SomeOther", 2);
System.out.println(map);
map.keySet().retainAll(fruit);
System.out.println(map);
System.out.println(map.keySet());
I have mobile numbers in database table column, in a format of country_code followed by mobile_number
So Mobile Number format is like this,
+91123456789 // country code of India is +91 followed by mobile number
+97188888888 // Country code of UAE +971
I have one HashMap containing CountryCodes of 5 countries like this,
map.put("+91","India")
map.put("+94","Sri Lanka")
map.put("+881","Bangladesh")
map.put("+971","UAE")
map.put("+977","Nepal")
My Bean Structure is something like this
class UserDetails {
// other fields
String countryCode;
String mobileNumber;
}
Now my task is to take the mobile number from Database table column and split it in two parts and set countryCode and mobileNumber, but country code length(in map's key) varies between 3 and 4. This checking can be done by using subString() and equals() but I don't think it's correct way, So what would be the elegant(may be checking in map key) way to solve this issue?
Although there is a library which seems to already do the trick, I think I'd go for an easy self-written solution:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class CountryExtractor {
private static final Map<String, String> COUNTRY_MAPPING = new HashMap<>();
static {
COUNTRY_MAPPING.put("+91", "India");
COUNTRY_MAPPING.put("+94", "Sri Lanka");
COUNTRY_MAPPING.put("+881", "Bangladesh");
COUNTRY_MAPPING.put("+971", "UAE");
COUNTRY_MAPPING.put("+977", "Nepal");
}
public static void main(String[] args) {
String[] inputs = new String[] { "+91123456789", "+97188888888" };
for (String input : inputs) {
System.out.println(Arrays.toString(parseNumber(input)));
}
}
private static String[] parseNumber(String number) {
for (String countryCode : COUNTRY_MAPPING.keySet()) {
if (number.startsWith(countryCode)) {
return new String[] { countryCode, number.replace(countryCode, "") };
}
}
return new String[0];
}
}
Output:
[+91, 123456789]
[+971, 88888888]
Note that this may not work correctly when a mobile prefix is a substring of another, but according to Wikipedia country calling codes are prefix codes and therefore guarantee that "there is no whole code word in the system that is a prefix (initial segment) of any other code word in the system".
IMHO a single map is better. An example;
public static void main(String args[]) throws Exception {
Map<String, String> map = new HashMap<>();
put(map, "+91", "India");
put(map, "+94", "Sri Lanka");
put(map, "+881", "Bangladesh");
put(map, "+971", "UAE");
put(map, "+977", "Nepal");
map = Collections.unmodifiableMap(map);
String mobileNumber = "+91123456789";
System.out.println(countryCode(map.keySet(), mobileNumber));
}
private static void put(Map<String, String> map, String key, String value) {
if (countryCode(map.keySet(), key) != null) {
throw new IllegalArgumentException("...");
}
map.put(key, value);
}
public static String countryCode(Set<String> countryCodes, String number) {
if (number == null || number.length() < 3) {
throw new IllegalArgumentException("...");
}
String code = number.substring(0, 3);
if (!countryCodes.contains(code)) {
if (number.length() > 3) {
code = number.substring(0, 4);
if (!countryCodes.contains(code)) {
code = null;
}
} else {
code = null;
}
}
return code;
}
You could use two maps for country code of different lengths and then search first for a match with 3 letters, and then with 4 letters.
HashMap<String, String > threeLetterCodes = new HashMap<String, String>();
threeLetterCodes.put("+91","India");
threeLetterCodes.put("+94","Sri Lanka");
HashMap<String, String > fourLetterCodes = new HashMap<String, String>();
fourLetterCodes.put("+881","Bangladesh");
fourLetterCodes.put("+971","UAE");
fourLetterCodes.put("+977","Nepal");
String test = "+97188888888";
String prefix = test.substring(0, 3);
String country = threeLetterCodes.get(prefix);
if (country == null) {
prefix = test.substring(0, 4);
country = fourLetterCodes.get(prefix);
}
System.out.println(country);
Output:
UAE
String format is (not json format):
a="0PN5J17HBGZHT7JJ3X82", b="frJIUN8DYpKDtOLCwo/yzg="
I want convert this string to a HashMap:
key a with value 0PN5J17HBGZHT7JJ3X82
key b with value frJIUN8DYpKDtOLCwo/yzg=
Is there a convenient way? Thanks
What I've tried:
Map<String, String> map = new HashMap<String, String>();
String s = "a=\"00PN5J17HBGZHT7JJ3X82\",b=\"frJIUN8DYpKDtOLCwo/yzg=\"";
String []tmp = StringUtils.split(s,',');
for (String v : tmp) {
String[] t = StringUtils.split(v,'=');
map.put(t[0], t[1]);
}
I get this result:
key a with value "0PN5J17HBGZHT7JJ3X82"
key b with value "frJIUN8DYpKDtOLCwo/yzg
for key a, the start and end double quotation marks(") is unwanted; for key b, the start double quotation marks(") is unwanted and the last equals sign(=) is missing.
Sorry for my poor english.
Probably you don't care that it's a HashMap, just a Map, so this will do it, since Properties implements Map:
import java.io.StringReader;
import java.util.*;
public class Strings {
public static void main(String[] args) throws Exception {
String input = "a=\"0PN5J17HBGZHT7JJ3X82\", b=\"frJIUN8DYpKDtOLCwo/yzg=\"";
String propertiesFormat = input.replaceAll(",", "\n");
Properties properties = new Properties();
properties.load(new StringReader(propertiesFormat));
System.out.println(properties);
}
}
Output:
{b="frJIUN8DYpKDtOLCwo/yzg=", a="0PN5J17HBGZHT7JJ3X82"}
If you absolutely need a HashMap, you can construct one with the Properties object as input: new HashMap(properties).
Added few changes in Ryan's code
public static void main(String[] args) throws Exception {
String input = "a=\"0PN5J17HBGZHT7JJ3X82\", b=\"frJIUN8DYpKDtOLCwo/yzg=\"";
input=input.replaceAll("\"", "");
String propertiesFormat = input.replaceAll(",", "\n");
Properties properties = new Properties();
properties.load(new StringReader(propertiesFormat));
Set<Entry<Object, Object>> entrySet = properties.entrySet();
HashMap<String,String > map = new HashMap<String, String>();
for (Iterator<Entry<Object, Object>> it = entrySet.iterator(); it.hasNext();) {
Entry<Object,Object> entry = it.next();
map.put((String)entry.getKey(), (String)entry.getValue());
}
System.out.println(map);
}
Split the String on the Basis of commas (",") and then with with ("=")
String s = "Comma Separated String";
HashMap<String, String> map = new HashMap<String, String>();
String[] arr = s.split(",");
String[] arStr = arr.split("=");
map.put(arr[0], arr[1]);
You can also use the regex as below.
Map<String,String> data = new HashMap<String,String>();
Pattern p = Pattern.compile("[\\{\\}\\=\\, ]++");
String[] split = p.split(text);
for ( int i=0; i+2 <= split.length; i+=2 ){
data.put( split[i], split[i+1] );
}
return data;