How can I extract the individual string values from a multimap? - java

My map is declared as:
ListMultimap<String, String> myMutlimap = ArrayListMultimap.create();
I've been able to print just the keys:
TEN
TT2
TP1
TP2
TRK
TAL
COM
COM
COM
TCO
TPA
TYE
or the values or the keys and values:
TEN=children's story
TT2=black star
TP1=black star
TP2=5/13
TRK=This old album
COM=This album is good
COM=This album is great
COM=This album is awesome
TCO=hip-hop
TPA=1/2
TYE=2002
But, when I try to list the value of the "COM" key I get:
[This album is good, This album is great, This album is awesome ]
How can I get the individual values of the "COM" key without resorting to string splitting the "=" sign away? I think if I could get the key and value on the same line, it would also make it easy to assign them to variables.
TEN children's story
TT2 black star
TP1 black star
TP2 5/13
COM This album is good
COM This album is great
COM This album is awesome
or
COM This album is good
This album is great
This album is awesome
I know that are ways I can use these keys and values as variables already but, I am looking for a clean and succinct way to do this - that also prints nicely.
Edit:
As requested here are some methods I've tried:
for (Object key : myMutlimap.keys()) {
System.out.println(key);
}
for (Object value : myMutlimap.values()) {
System.out.println(value);
}
for (Object value : myMutlimap.entries()) {
System.out.println(value.toString());
}
for (String value : myMutlimap.keySet()) {
System.err.println(value);
System.out.println(myMutlimap.get("COM"));
}

Just use get() and iterate over the list that it returns to get the values individually.
List<String> values = myMutlimap.get("COM");
for (String s: values) {
System.out.println(s);
}

You're not using the type parameters of the Multimap (or even the return type of the methods, for that matter), so of course Object won't get you far.
With an instance of Multimap<String, String>, you have the following (interesting) methods available:
Map<String, Collection<String>> asMap() to get the Map view, where each key has a collection of values
Collection<Map.Entry<String, String>> entries() to get the individual entries, i.e. each (key, value) pair
Collection<String> get(String key) to get all the values for a given key
Multiset<String> keys() to get all the keys without duplicates and be able to know how many values are associated to each of them
Set<String> keySet() to get the Set of keys, again without duplicates
Collection<String> values() to get the collection of all values present in the Multimap, without knowing which key they are associated to
Knowing that, if you want to print the values for a given key, you just have to do this:
for (String value : myMultimap.get("COM")) {
System.out.println(value);
}
If you want to do the same for all available keys, you have several options:
Iterate on the keys and lookup their values:
for (String key : myMultimap.keySet()) {
for (String value : myMultimap.get(key)) {
System.out.println(key + " " + value);
}
}
Iterate on the entries of the Multimap (the (key, value) pairs):
for (Map.Entry<String, String> entry : myMultimap.entries()) {
String key = entry.getKey(), value = entry.getValue();
System.out.print(key + " " + value);
}
Iterate on the entries of the Map view:
for (Map.Entry<String, Collection<String>> entry :
myMultimap.asMap().entrySet()) {
String key = entry.getKey();
Collection<String> values = entry.getValue();
for (String value : values) {
System.out.println(key + " " + value);
}
}
This method has the advantage of giving you access to the collection of values for each key (so you have a nice collection with all its available methods, like size(), or that could can manipulate further), like in option 1, but without the need of an extra lookup in the Multimap for each key.

Related

in Java, how can I map String to a Set<String> if I do not know how many keys in total

I need a HashMap, which the key is String and value is Set, like:
Key: "a", Value: {"a","b","c"....}
Key: "b", Value: {"a,","d"....}
...
But I do not know how many keys in total, it depends on the result from other method.
So basically, here is the method looks like: (map could be field)
public void mapKeyValue(int numbersOfKey, HashMap map){
//some code
}
So if I write the code like this:
public void mapKeyValue(int numbersOfKey, HashMap map){
for (int i = 0; i < numbersOfKey; i++){
Set<String> set = new HashSet<String>();
set.add("some strings");// we can add some strings here
map.put("OneString", set);
}
}
After the method, I will get nothing because I will lose all the Set object created by the method, so I cannot get the Set by calling map.get("OneString").
So what should I do if I want to get that hashMap?
There are a number of issues with your code, but I suggest the following approach.
In your case, it looks like you have a Map<String, Set<String>> which is a map of String keys to a set of Strings.
If that's what you were after, I suggest that you
check if the key has a value. If not add an empty set for the key to the surrounding map.
Fetch the set from the map by it's key.
add or remove any desired values from the set
Note that your code as it is written, always replaces the Set stored with the key "OneString" meaning that regardless of value "numbersOfKey" you are really just rebuilding the set at the single key "OneString" numbersOfKey times.
You probably want to do something like
public void addToSet(String setName, String value) {
if (!sets.containsKey(setName)) {
sets.put(setName, new HashSet<String>());
}
Set<String> values = sets.get(setName);
values.add(value);
}
This block assumes you have somewhere in the class a member variable like
private Map<String, Set<String>> sets = new HashMap<>();
Note that this code is an idea, and not production code. In the real world, what you add probably should eventually be removed at some point in time. As such, you want to have a facility to remove specific values, or entire sets of values along with their keys at some future point of your program's execution.
you can not do that?
public HashMap<String, Set<String>> mapKeyValue(int numbersOfKey){
HashMap<String, Set<String>> map = new HashMap<>();
for (int i = 0; i < numbersOfKey; i++){
Set<String> set = new HashSet<String>();
set.add("some strings" + "" + i);// we can add some strings here
map.put("OneString", set);
}
return map;
}
I would suggest using the Apache Commons Collection MultiValueMap instead of creating a Set each time. Both work just fine, but there is a Map that does all of that for you and it's based on a HashMap, keeping your constant time access. Javadoc here:
https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/MultiValueMap.html
Something like this...
public void someOtherMethod() {
// Assuming the Map is created and used somewhere outside the mapKeyValue method. Otherwise it should be instantiated inside the mapKeyValue method
MultiValueMap<String, String> map = new MultiValueMap<>();
//2 is an arbitrary, made up number that you select somehow
mapKeyValue(2, map);
//Access the values of the map dynamically without knowing how many keys there are
for (String key : map.keySet()) {
System.out.print(key + " : ");
for (String value : map.getCollection(key)) {
System.out.print(value + ", ");
}
}
}
public MultiValueMap<String, String> mapKeyValue(int numbersOfKey, MultiValueMap<String, String> map){
for (int i = 0; i < numbersOfKey; i++){
//We need to create a unique key here, so let's use 'i'
//There are several ways to skin the cat and get the int to String
//Also want to create unique values, but that's up to you, they're not required to be unique
map.put(Integer.toString(i), Integer.toString(i) + "a");
map.put(Integer.toString(i), Integer.toString(i) + "b");
map.put(Integer.toString(i), Integer.toString(i) + "c");
}
//At this point, the map has in it the following key : value pairs
//"0" : ["0a", "0b", "0c"]
//"1" : ["1a", "1b", "1c"]
//"2" : ["2a", "2b", "2c"]
//Not technically required to return the map IFF the map is instantiated outside the method
return map;
}

Java - Adding another String value to existing HashMap Key without overwriting?

I was wondering if someone would be able to help with regards to adding another String value to an existing key within a HashMap in Java?
I understand that you can add a Key-Value pair using the this.put("String", "String") method. However, it overwrites the existing value, whereas I would like multiple values stored and paired, with the same key?
Thanks for your help.
What are you hoping to achieve here?
A Map (the HashMap) in your case is a direct "mapping" from one "key" to another value.
E.g.
"foo" -> 123
"bar" -> 321
"far" -> 12345
"boo" -> 54321
This means that if you were to try:
myHashMap.get("foo");
It would return the value 123 (of course, the type of the value you return can be anything you want).
Of course, this also means that any changes you make to the value of the key, it overrides the original value you assigned it, just like changing the value of a variable will override the original one assigned.
Say:
myHashMap.put("foo", 42);
The old value of "foo" in the map would be replaced with 42. So it would become:
"foo" -> 42
"bar" -> 321
"far" -> 12345
"boo" -> 54321
However, if you need multiple String objects that are mapped from a single key, you could use a different object which can store multiple objects, such as an Array or a List (or even another HashMap if you wanted.
For example, if you were to be using ArrayLists, when you are assigning a value to the HashMap, (say it is called myHashMap), you would first check if the key has been used before, if it hasn't, then you create a new ArrayList with the value you want to add, if it has, then you just add the value to the list.
(Assume key and value have the values you want)
ArrayList<String> list;
if(myHashMap.containsKey(key)){
// if the key has already been used,
// we'll just grab the array list and add the value to it
list = myHashMap.get(key);
list.add(value);
} else {
// if the key hasn't been used yet,
// we'll create a new ArrayList<String> object, add the value
// and put it in the array list with the new key
list = new ArrayList<String>();
list.add(value);
myHashMap.put(key, list);
}
You can do like this!
Map<String,List<String>> map = new HashMap<>();
.
.
if(map.containsKey(key)){
map.get(key).add(value);
} else {
List<String> list = new ArrayList<>();
list.add(value);
map.put(key, list);
}
Or you can do the same thing by one line code in Java 8 style .
map.computeIfAbsent(key, k ->new ArrayList<>()).add(value);
Would you like a concatenation of the two strings?
map.put(key, val);
if (map.containsKey(key)) {
map.put(key, map.get(key) + newVal);
}
Or would you like a list of all the values for that key?
HashMap<String,List<String>> map = new HashMap<String,List<String>>();
String key = "key";
String val = "val";
String newVal = "newVal";
List<String> list = new ArrayList<String>();
list.add(val);
map.put(key, list);
if (map.containsKey(key)) {
map.get(key).add(newVal);
}
As others pointed, Map by specification can have only one value for a given key. You have 2 solutions:
Use HashMap<String, List<String>> to store the data
Use Multimap which is provided by 3rd party Google Collections lib
As described in Map interface documentation Map contains a set of keys, so it is not capable of containing multiple non-unique keys.
I suggest you to use lists as values for this map.
Store value as list under map So if key is test and there are two values say val1 and val2 then key will be test and value will be list containing val1 and val2
But if your intention is to have two separate entries for same key, then this is not Map is designed for. Think if you do map.get("key"), which value you expects
You could use Map<String, Collection<String>> but adding and removing values would be cumbersome . Better way is using guava Multimap - a container that allows storing multiple values for each key.
You can't directly store multiple values under a single key, but the value associated with a key can be any type of object, such as an ArrayList, which will hold multiple values. For example:
import java.util.ArrayList;
import java.util.HashMap;
public class HashMapList {
HashMap<String, ArrayList<String>> strings = new HashMap<String, ArrayList<String>>();
public void add(String key, String value) {
ArrayList<String> values = strings.get(key);
if (values == null) {
values = new ArrayList<String>();
strings.put(key, values);
}
values.add(value);
}
public ArrayList<String> get(String key) {
return strings.get(key);
}
public static void main(String[] argv) {
HashMapList mymap = new HashMapList();
mymap.add("key", "value1");
mymap.add("key", "value2");
ArrayList<String> values = mymap.get("key");
for (String value : values) {
System.out.println(value);
}
}
}
it's impossible,because String is immutable if you use the String as the key of map the same key's value has the same hashcode value.

Compare keys with llist of values Java

Assuming the TreeMap<String,List> one and its copy as bellow,
i want to compare all keys in the first one with all values in the second one. If a key has no match in values, as AUF_1060589919844_59496 and AUF_1421272434570_1781 in this case, i want to get the key and its values back.
{AUF_1060589919844_59496=[AUF_1086686287581_9999,
AUF_1086686329972_10049, AUF_1079023138936_6682],
AUF_1087981634453_7022=[AUF_1421268533080_1741, AUF_1421268568003_1743],
AUF_1421268533080_1741=[AUF_1421268719761_1776],
AUF_1421272434570_1781=[AUF_1087981634453_7022]}
copy of above
{AUF_1060589919844_59496=[AUF_1086686287581_9999,
AUF_1086686329972_10049, AUF_1079023138936_6682],
AUF_1087981634453_7022=[AUF_1421268533080_1741, AUF_1421268568003_1743],
AUF_1421268533080_1741=[AUF_1421268719761_1776],
AUF_1421272434570_1781=[AUF_1087981634453_7022]}
What I understand from your problem is to get key which are not there in values and its value also. I think there is no need to create copy of it. I am posting a code snippet, I think this will certainly help you
Map<String, List<String>> map = new HashMap<String, List<String>>(); //Add elements in map
Collection<List<String>> list = map.values();
List<String> values = new ArrayList<String>();
for (List<String> listValues : list) {
values.addAll(listValues);
}
for (String key : map.keySet()) {
if (!values.contains(key)) {
System.out.println("key ---->" + key);
System.out.println("Values ------->");
for (String value : map.get(key)) {
System.out.println(value);
}
}
}
If my assumption is correct you want all the keys that are not values;
well this is very dirty way of doing it.
Set<String> keys= new HashSet<String>(one.keySet()); //ensure we don't mess up with the actual keys in the Map
for(List list : one.values()){
keys.removeAll(list); //remove all those Keys that are in values
}
// print out keys that are not values
System.out.println(keys);
Using set will make life easy, as it doesn't contain duplicates, and we can remove values very quicky (using removeAll() method)

How to add HashMap values to List and print the same

I am trying to add map values to list for my scenario as below.
I have select statement which returns n-no of columns and row, I am storing them into List of Hash Map of type String and pass it to some other method to produce an EXCEL file out of the result.
i am unable to see any data in the list
Please advice where i am going wrong.
while (result.next()) {
resultValues.put("PARTC_ID",result.getString("PARTC_ID"));
resultValues.put("FILE_NME",result.getString("FILE_NME"));
resultValues.put("LOC_ID",result.getString("LOC_ID"));
resultValues.put("CRTE_DTE",result.getString("CRTE_DTE"));
resultValues.put("CRTE_BY",result.getString("CRTE_BY"));
value.add(resultValues); resultValues.clear(); System.out.println(value);
}
You're clearing your Map after adding it to the List. The Map references are all thus the same (and empty)... I think you want to make this change -
// resultValues.clear(); // No, if you need another Map... do this
resultValues = new HashMap<String, String>();
Then to iterate your value List try
for (HashMap<String, String> map : value) {
for (String key : map.keySet()) {
System.out.printf("key[%s] = %s\n", key, map.get(key));
}
}

Getting the key and its specific value from map

I am using Map as follows
Map<String, String> propMap = new LinkedHashMap<String, String>();
and I saw that there is two methods that I can use keySet() (to get the list of keys)
and values to get the list of values but my question is how to relate between them
for example for key1 the value is 2.
I thought to use get value like follows
Map<String, String> propMap2 = propterm.getPropMap();
Set<String> keySet = propMap2.keySet();
But how I relate it to his respective value ?
You can use propMap.entrySet() method which returns a Map.Entry of key, value, if you want to use every pair of key and value: -
for (Map.Entry<String, String> entry: propMap.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
Or, if you want to know how to do this with propMap.keySet(), you can iterate over the Set<Key> you obtain, and for each key, use propMap.get(key), to get the value of a particular key: -
Set<String> keySet = propMap2.keySet();
for (String key: keySet) {
System.out.println(propMap.get(key));
}
From an answer from this post: -
With the later approach, if you are regularly accessing the key-value pair, then for each key, the map.get() method is called, which - in the case of a HashMap - requires that the hashCode() and equals() methods of the key object be evaluated in order to find the associated value*. In the first case (entrySet), that extra work is eliminated.

Categories

Resources