Unable to retrieve multi line value using map.get() - java

I have a multi-line value that needs to be processed. I'm using the map.get() method to retrieve that value but it seems to be getting only the last line value.
Here's my code:
map = new LinkedHashMap();
updateMap("BUG", parser, map, bugRec);
map.put(nextBuildIdTagName, nextBuildId); // putting the new value in
String value = (String)map.get(nextBuildIdTagName); // This is where it is not working
nextBuildIdTagName already has a value, and the new value gets inserted as a new line. I need to be able to retrieve the existing value as well as the new value.

So from what I understand you want to store multiple values in the map under single key. Easiest way to do it (without using any external lib with multimap impl) is to create a map of lists like this:
Map<String, List<String>> map = new HashMap<>();
then when you add to map you can do sth like this:
if(!map.containsKey(nextBuildIdTagName)) {
map.put(nextBuildIdTagName, new ArrayList<>());
}
map.get(nextBuildIdTagName).add(nextBuildId);
then to get all the items and iterate over them
for(String value : map.get(nextBuildIdTagName)) {
// do sth to each line
}

In the javadoc for HashMap (of which LinkedHashMap is a subclass), it is clearly stated that: "If the map previously contained a mapping for the key, the old value is replaced". To store multiple values (the lines) for the same key, you'd need to do something like:
Map<String, List<String>> map = new Linked HashMap<>();
And the add to the list (which is the map value) the needes lines. Note: here I assumed your key to be a String, change its type as needed.
Source: http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put(K,%20V)

Related

Store the values without overwriting

I have a Map<String, Integer> e.g.
"aaa", 1
"bbb", 2
"ccc", 3
"aaa", 4
The problem is that the HashMap does not store all key and values, as I've understood, when i try add the last pair ("aaa", 4), it will not be added, instead of this, the value for "aaa" (I mean 1) will be overwritten on 4.
I know, that I could create class, where I could store these pairs, but I need another solution. (without creating a new class)
EDIT ------------------------------------
Actually I have much more pairs, and I do not have uniques String or Integers, I mean that, if even I have two similar pairs they will be stored
A map, by definition, will have distinct keys. If you add a key-value pair and the key already exists, the new key-value pair will overwrite the existing key-value pair.
For your scenario, when you have multiple values against a single key, you can explore the following options
Option 1 : Since your key-value pairs are not unique, it can be stored as list of pairs. For every key-value pair, you can create a pair and insert it into the list.
List<Pair<String, Integer>> data = new ArrayList();
Pair<String, Integer> item = new Pair("abc", 1);
data.add(item);
This option does not give you optimized lookup capabilities that comes with Map.
Option 2. Create a Map<String, List<Integer>>. You'll not be able to do simple put operations on the map anymore, but you will be able to store all the items corresponding to each key without loss of information as well as retrieve them faster.
Create a List:
if (!map.containsKey("aaaa")) {
map.put("aaaa", new ArrayList<Integer>());
}
List<Integer> aaaaValues = map.get("aaaa");
aaaaValues.add(1);
aaaaValues.add(4);
...
If your values are unieque, use them as keys.
You don't have to create class. You can use List<org.apache.commons.lang3.tuple.Pair<String, Integer>>
Also one way, override equals and hashCode where you speak that object is unique only if String and Integer parameter is unique in pair
Map<String, Integer> map = new HashMap<String, Integer>(){
#Override
public boolean equals(Object o)
{
// your realization
}
#Override
public int hashCode()
{
// your realization
}
};

Java: How to properly remove a value from a HashMap NOT based on the key

I have a Singleton class that inside has a HashMap. The HashMap is made of String and Set<String>:
private Map<String, Set<String>> mMap = new HashMap<>();
What I want to achieve?
Remove a given item from all the Set values inside the Map. For example:
mMap.put(keyName, new HashSet<String>())
....
mViewsSwipeStates.get(keyName).add("1");
mViewsSwipeStates.get(keyName).add("2");
mViewsSwipeStates.get(keyName).add("3");
....
//Remove an item from the set
mMap.values().remove("3"); //Does not work
What is the correct way to remove an item from inside the Set?
I'm assuming you want to remove productCode from all the values of the Map (and not just from the value of a specific key).
You have to iterate over all the values of the Map, and remove from each of them the required element :
mMap.values().forEach(v->v.remove(productCode));
This code assumes there are no null values in the Map.
EDIT :
In Java 7 you can write:
for (Set<String> value : mMap.values()) {
value.remove(productCode);
}
Iterate over all map entries, mutating the value for each:
map.forEach((k, v) -> v.remove(productCode)};
using java 8 and lambda expressions
map.forEach((key, value) -> value.remove(productCode));

iterate through all the values of a key in hashtable java

Hashtable<Integer,String> ht = new Hashtable<Integer,String>();
ht.put(1,"student1");
ht.put(1,"student2");
How can I iterate through all values of "a single key"?
key:1
values: student1, student2
You need to use:
Hashtable<Integer, List<String>> ht = new Hashtable<Integer, List<String>>();
and add the new String value for a particular key in the associated List.
Having said that, you should use a HashMap instead of Hashtable. The later one is legacy class, which has been replaced long back by the former.
Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();
then before inserting a new entry, check whether the key already exists, using Map#containsKey() method. If the key is already there, fetch the corresponding list, and then add new value to it. Else, put a new key-value pair.
if (map.containsKey(2)) {
map.get(2).add("newValue");
} else {
map.put(2, new ArrayList<String>(Arrays.asList("newValue"));
}
Another option is to use Guava's Multimap, if you can use 3rd party library.
Multimap<Integer, String> myMultimap = ArrayListMultimap.create();
myMultimap.put(1,"student1");
myMultimap.put(1,"student2");
Collection<String> values = myMultimap.get(1);
A Hashtable doesn't store multiple values for a single key.
When you write ht.put(1, "student2"), it overwrites the value that goes with "1" and it is no longer available.
Hashtable doesn't allow multiple values for a key. When you add a second value to a key, you're replacing the original value.
If you want multiple values for a single key, consider using a HashTable of ArrayLists.

Can't figure out how to retrieve objects in a map

I have a
Map<String, List<String>> myMap;
I'm having a hard time retrieving the objects in the List:
For example I can retrieve from the Map
String myString = myMap.get("Toyota").toString();
but how do I retrieve from the List?
Lets say that the List contains all the models for each car brand. How can I retrieve only the item 0 in that that List?
Thanks
myMap.get("Toyota").get(0) - That should do it.
The reason is that you ask myMap the value that is pointed by the key "Toyota". As you defined in your definitions, the values are always of type List<String> which means that the call myMap.get("Toyota") returns a List<String> object. When you do a get(0) call you actually call the get method of List<String>
You need to retrieve the List and then its contents :
//myMap.get(key).get(listIndex);
// myMap.get("Toyota"); // gets the List object
myMap.get("Toyota").get(0);
Hence , you need to use Map#get() and then List#get().
The statement myMap.get("Toyota") will return the List type which is value for the key Toyota. You can get the first element of list using myMap.get("Toyota").get(0)
Basically when you use a Map and want to retrieve values based on certain key, you can iterate over the Map and retrieve them as follows :
for (final Entry<String, List<String>> entry : myMap.entrySet()) {
String key = entry.getKey();
List<String> value = entry.getValue();
}
As you can see, inside the for loop, you have both key and the value. You can do the further processing here after.

Retrieving the previous key-map value before it was overwritten in a HashMap

I have created a HashMap as per my code...
HashMap map=new HashMap();//HashMap key random order.
map.put("Amit","Java");
map.put("Saral","J2EE");
map.put("Saral","Andriod");//same key but different value
map.put("Nitin","PHP");
map.put("hj","Spring1");
System.out.println("There are "+map.size()+" elements in the map.");
System.out.println("Content of Map are...");
Set s=map.entrySet();
Iterator itr=s.iterator();
while(itr.hasNext()){
Map.Entry m=(Map.Entry)itr.next();
System.out.println(m.getKey()+"\t"+m.getValue()+"\t"+ m.hashCode());
}
When I execute this code, the value for key=Saral is Android. Is there any way that I can get the previous value for this key, which was J2EE?
No, you can't have that with a standard HashMap. The easiest solution would be to store a List as value in the map though, and then you can add multiple items to the list (Btw you should use generic collections too). To simplify, you could use a helper method like this:
void addToMap(Map<String, List<String>> map, String key, String value) {
List<String> list = map.get(key);
if (list == null) {
list = new ArrayList<String>();
map.put(key, list);
}
list.add(value);
}
Map<String, List<String>> map = new HashMap<String, List<String>>();
addToMap(map, "Amit", "Java");
addToMap(map, "Saral", "J2EE");
addToMap(map, "Saral", "Andriod");//same key but different value
addToMap(map, "Nitin", "PHP");
addToMap(map, "hj", "Spring1");
...
The helper method here is just an illustration - a full, robust implementation may need to include e.g. checks for duplicate values, depending on whether you allow them. If not, you may prefer using a Set instead of List.
Update
To print out the contents of this map, you need to use an embedded loop to iterate through the list of values for each map entry (btw you can use a foreach loop instead of an iterator):
for (Map.Entry<String, List<String>> m : map.entrySet())
{
for (String v : m.getValue())
{
System.out.println(m.getKey()+"\t"+v+"\t"+ m.hashCode());
}
}
A Map can contain at most one entry per key, so when you call map.put("Saral","Andriod"), the old "J2EE" value is removed. To support multiple values per key, you would need to maintain a Map<String, List<String>> or else a multi-map implementation such as Guava's Multimap.
As a side note I would recommend you start using generics, for example Map<String, String>, Iterator<String>, etc. for type safety at compile time.
The old value is overwritten (replaced). There will be only one mapping (entry) for one unique key. There fore it does not exist anymore so you can not retrieve it.
You cannot do this with standard implementations of Map that Java provides. However there are implementations of MultiMap (that's basically what you're after).
One example is this one from Google:
http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/Multimap.html
Note that you won't be able to just get this one interface, you'll need a few classes along with it.
As other have said, this won't work with a standard Map. However, Google's Guava provides a MultiMap interface, which you can use to store multiple values with a single key.
Example of use:
Multimap<String,String> multiMap = ArrayListMultimap.create();
multiMap.put("color", "red");
multiMap.put("color", "blue");
System.out.println(multiMap.get("color")); //returns a ["red', "blue"] list

Categories

Resources