How to put multiple values in Map from a list - java

I have a list gotitems.
ArrayList<String> gotitems = new ArrayList<String>();
i need to put that list in a hashmap called map.
Map<String,String> map = new HashMap<String,String>();
i had tried this :
for(String s:gotitems){
map.put("a",s);
}
gotitems contains :
First
Second
Third
But the output of :
System.out.println(map.values());
gives :
Third
Third
Third
i had even tried this :
for(String s:gotitems){
for(int j=0;j<gotitems.size();j++){
map.put("a"+j,s);
}
}
but this is also not working.
What am i doing wrong here ?

As per Map put(K,V) method docs
Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for the key, the old value is replaced by the specified value.
You are ovverriding the key each time here .
for(String s:gotitems){
map.put("a",s);
}
change the key each time and try like
for(String s:gotitems){
map.put(s,s);
}

This is because you are putting all the items in the map against the same key "a"
map.put("a");
You need to store each element against a unique key so add something like this:
int count = 0;
for(String s:gotitems){
map.put("a" + count,s);
count++;
}

You are trying to put three Strings in the map under the same key "a". Try to use unique keys for your values.

You're putting all your items in the Map with the same key: "a".
You should have a unique String key for each value.
For instance:
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
Map<String, String> map = new LinkedHashMap<String, String>();
for (String s: list) {
map.put(s, s);
}
System.out.println(map);
Output:
{one=one, two=two, three=three}
Note the LinkedHashMap here: it maintains the order in which you put your key/value pairs.
Edit Of course if your List does not have unique values, moving its values as keys to a Map will overwrite some of the Map's values. In that case you want to ensure your List has unique keys first, or maybe use a Map<Integer, String> with the index of the List's value as key to the Map, and the actual List value as value to the Map.

When you write
for(String s:gotitems){
map.put("a",s);
}
you will trash any existing entry in the map held against the key "a". So after your iteration, your map will contain just one entry corresponding to the last iterated value in gotitems.
To use a map effectively you need to consider what your keys will be. Then use map.put(myKeyForThisItem, s) instead. If you don't have an effective scheme for the keys then using a map is pointless as one tends to use the keys to extract the corresponding values.
As for your second approach, it would be helpful if you could define "it is not working" a little clearer: perhaps iterate through the map and print the keys and values.

Please note that in a map, a key can point to at most one value. In your case, you are doing the following mappings:
"a" -> "one"
then you overwrite it as
"a" -> "two"
then you overwrite it as
"a" -> "three"
remember: a key can point to at most one value. However, a value can be pointed at by multiple keys.

This is wrong:
for(String s:gotitems){
map.put("a",s);
}
Since you are using "a" common key for all values, last inserted key-value pair would be preserved, all previous ones would be overridden.
This is also not correct:
for(String s:gotitems){
for(int j=0;j<gotitems.size();j++){
map.put("a"+j,s);
}
}
you are putting n*n times into map, though you want only n (gotitems.size()) items into map.
First decide on key which you want to use in map, copying List into Map one approach could be use index as key:
for(int j=0;j<gotitems.size();j++){
map.put("KEY-"+j,gotitems.get(j));
}
Output should be:
KEY-0 First
KEY-1 Second
KEY-2 Third

I have reproduce your codes. The problem is that you are assigning the same key to different value. This should work.
import java.util.*;
public class testCollection{
public static void main(String[] args){
ArrayList<String> gotitems = new ArrayList<String>();
gotitems.add("First");
gotitems.add("Second");
gotitems.add("Third");
Map<String,String> map = new HashMap<String,String>();
String x = "a";
int i = 1;
for(String s:gotitems){
map.put(x+i,s);
i++;
}
System.out.println(map);
}
}

Related

Removing duplicate linked value from ArrayList java

we are facing a challenge in implementing one of our client requirement, using java as code technology.
we need to format the input given by the system, to display the data in a userfriendly format.
below is the data as input to our program.
its a java map with key as string and value as a list of strings
OP1004=[],
OP1006=[OP1004]
OP1005=[OP1003]
OP1009=[OP1006, OP1044, OP1046, OP1004],
OP1016=[OP1008, OP1009, OP1044, OP1005, OP1004],
output we are expecting as below.
OP1004=[],
OP1006=[OP1004]
OP1005=[OP1003]
OP1009=[OP1006, OP1044, OP1046], //here 1004 is deleted
OP1016=[OP1008, OP1009, OP1005, OP1004], //here 1044 is deleted
here, if we observe closely, we want to delete the repeated values from the list, that is
if we go thru the bottom, that is OP1016 contains the list as OP1008, OP1009 etc.. where OP1009 also has the list as OP1006, OP1044 etc.. where OP1006 again has the list as OP1004
so here we want to delete OP1004 from OP1009 because its already mapped to other(OP1006) OPID which is part of OP1009.
actually we are displaying this in a hierachy/flowchart diagram, so we want to delete duplicate navigation to the items.
Please help us in providing solution. appreciate your help in advance.
Thanks
Your problem boils down to checking whether elements of a list are present in other lists but these list are present in a map so you need to maintain the key-value pair.
This is how you can achieve that.
Loop over map and get the key and list of values, add a condition to check whether list is empty and contains more than 1 values.
Loop over same map again, get the key and add a condition to check whether the first loop key is equal to second loop key this is to avoid checking for same list. Add one more condition to check whether list is empty and contains more than 1 values.
Now you can remove elements from a list if those elements are present in another list by using List.removeAll() method.
Sample code
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Example {
public static void main(String[] args) {
List<String> firstList = new ArrayList<String>();
firstList.add("");
List<String> secondList = new ArrayList<String>();
secondList.add("OP1004");
List<String> thirdList = new ArrayList<String>();
thirdList.add("OP1003");
List<String> fourthList = new ArrayList<String>();
fourthList.add("OP1006");
fourthList.add("OP1044");
fourthList.add("OP1046");
List<String> fifthList = new ArrayList<String>();
fifthList.add("OP1008");
fifthList.add("OP1009");
fifthList.add("OP1044");
fifthList.add("OP1005");
fifthList.add("OP1004");
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("OP1004", firstList);
map.put("OP1006", secondList);
map.put("OP1005", thirdList);
map.put("OP1009", fourthList);
map.put("OP1016", fifthList);
for (Map.Entry<String, List<String>> keyAndValue: map.entrySet()) {
String key = keyAndValue.getKey();
List<String> values = keyAndValue.getValue();
if (values.isEmpty() || (values.size() < 2)){
continue;
}
for (Map.Entry<String, List<String>> mapKeyAndValue: map.entrySet()) {
String key1 = mapKeyAndValue.getKey();
if (key.equals(key1)){
continue;
}
List<String> values2 = mapKeyAndValue.getValue();
if (values2.isEmpty() || (values2.size() < 2)){
continue;
}
values2.removeAll(values);
}
}
for (Map.Entry<String, List<String>> keyAndValue: map.entrySet()) {
System.out.println("Key is " + keyAndValue.getKey() + " Values are " + keyAndValue.getValue());
}
}
}
Check Output Here
Key is OP1004 Values are []
Key is OP1006 Values are [OP1004]
Key is OP1005 Values are [OP1003]
Key is OP1009 Values are [OP1006, OP1044, OP1046]
Key is OP1016 Values are [OP1008, OP1009, OP1005, OP1004]
Note - I assumed that you are using HashMap as you didn't specify what kind of map you are using and if you want the map to be ordered then use LinkedHashMap
as HashMap does not store elements in order.
A simple solution would be to change the
Map<String, List<String>> to Map <String<Set<String>>
Let me explain it in a better way:
List list = map.get(str);
Set<String> set = new HashSet<>();
set.addAll(list);
list.clear();
list.addAll(set);
now you can use it in the way you want..
Let me know if you didnt understand any part of it
Pseudo-code: if key exists then remove it from any values (of other keys)
for (String key : map.keySet()){ // iterate through all keys
for (Map.Entry<String, List> mapEntry : map.entrySet()){ // again iterate but this time get Map.Entry
if (!mapEntry.getKey().equals(key)){ // if entry is for other key
((List)mapEntry.getValue()).remove(key); // then remove key from list
// if this map cannot be modified you can keep key, mapEntry in another map here...
}
}
}
Create a set to hold all the values previously displayed. If an item can not be added to this set, then do not add it at all.
Map<String, String[]> original = ...
Set<String> used = new HashSet<>();
Map<String, String[]> reduced = original
.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
entry -> Arrays.stream(entry.getValue())
.filter(used::add)
.toArray(String[]::new)));

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.

Java Iterate through a HashMap<?, List<?>> and for each Key count how many Values the Key has

I'm having problems on how to tackle this since I know a map has no specific order. I would think that you would iterate over the map's Keys and then check the value count by getting the size of the LinkedList since the Values to the Key are held in a LinkedList I can just call a size or length call for the LinkedList, but my main question is how to get inside the HashMap with an iterator first to do this?
An iterator over all the entries of a map can be done as follows in Java:
for (Map.Entry<Key, Value> entry : map.entrySet()) {
Key k = entry.getKey();
Value v = entry.getValue();
// do something with k,v
}
However, a map can only contain at most one value associated with a key. So, if using a map of lists to associate multiple values, the list would be accessed simply through get.
I suppose you have something like this :
Map<Integer,List<Integer>> map = new HashMap<>();
You can just iterate very simply through all the values you have.
for (List<Integer> values : map.values()){
System.out.println(values.size());
}

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)

HashMap delete entry AND position

I'm just working with HashMaps and now it pops up a question I actually can't answer by myself...
In my HashMap there are some entries. I'm now searching through all the entries for a certain value. If that value is found It delete it using hashmap.remove();. But I don't "only" want to delete the entry but the whole "position" of the HashMap so that there is no blank space between it. In the end the HashMap shouldn't have any value anymore (I think it will be null then, won't it?)
Is there any possible way to do so?
That's what I got so far but it only deletes the entry not the whole position...
for (Entry<Integer, String> entry : myMap.entrySet()) {
if (entry.getValue().contains("EnterStringHere")) {
myMap.remove(entry);
}
}
This is wrong
for (Entry<Integer, String> entry : myMap.entrySet()) {
if (entry.getValue().contains("EnterStringHere")) {
myMap.remove(entry); // you should pass the key to remove
}
}
But you can't use this way to remove element. You will get ConcurrentModificationException.
You can try this way using iterator to remove element while iterating.
Map<Integer,String> map=new HashMap<>();
map.put(1,"EnterStringHere");
map.put(2,"hi");
map.put(3,"EnterStringHere");
Iterator<Map.Entry<Integer,String>> iterator=map.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Integer,String> entry=iterator.next();
if(entry.getValue().equals("EnterStringHere")){
iterator.remove();
}
}
System.out.println(map);
Out put:
{2=hi}
You really need to see HashMap#remove()
You cannot remove the entry object from a Map. The remove method expects key.
Instead you can try the below:-
Iterator<Entry<Integer, String>> itr = myMap.entrySet().iterator();
while(itr.hasNext()) {
Entry<Integer, String> entry = itr.next();
if (entry.getValue().contains("EnterStringHere"))
{
itr.remove();
}
}
Also you cannot directly structurally modify a Map while iterating else you will get ConcurrentModification Exception. To prevent this you need to delete using the remove method on the iterator as shown in above code.
Let's say you got a Map<Key,Value> size of 10 and you want to remove 8th key value pair in current Map. What happen is Map become the size of 9 and there will be another key value pair in 8th position.
You can't to beyond that with remove(). You can't remove the position.
But when you use Map.get(removed_key) you will get null since there is no key there now.
Eg:
Map<String,Integer> map=new HashMap<>();
map.put("a",1);
map.put("b",2);
map.put("c", 3);
System.out.println("size of the map "+map.size() +" map is "+map);
map.remove("b");
System.out.println("size of the map "+map.size() +" map is "+map);
System.out.println(map.get("b"));
Out put:
size of the map 3 map is {b=2, c=3, a=1}
size of the map 2 map is {c=3, a=1}
null // you are getting null since there is no key "b"
Adding this to provide answer to your comment,If you want to check whether map is empty. simply use map.isEmpty()
Understanding how HashMap works here Link.
Also see java doc here link.
If you want to set pack your hashmap try to check size of the map then delete one then check size again for example.
hashmap.size(); => 10
hashmap.remove(obj);
hashmap.size() => 9
this means the hashmap is packed and will not have any empty entry. At the end hashmap will automatically will not contain any value in it
Because after a certain time I need to check if the HashMap is empty. But another answer seems to get the hint I needed. If I delete the value the entry will be null? Can i do a check if every entry is null easily or do i have to iterate over every entry again?
You do not delete a value from a Map you delete a mapping. this code does not delete any thing:
myMap.remove(entry);
because you pass the entry object, you need to pass the key of the mapping on order to delete it, see Map.html#remove docs.
thus
myMap.remove(entry.getkey());
However with the current approach you will run in ConcurrentModificationException. If it didnt till now it's just because your code didn't delete anything, because you pass the entry object
If you delete the mapping from the map, that mapping will no longer exist in the map. Whether the bucket is null or not is implementation detail, but when you query a mapping that was deleted using the given key you'll get null as return value. If you add another mapping with the same key you will get taht mapping again.
You can check if a map is empty using Map#isEmpty, thus you dont need to check if every entry is null or iterate over the whole map to do so.
You can check if a map contain a mapping for a key using Map.#containsKey
You can check if a map caintains at least one mapping for a value using Map#containsValue
the correct way to delete etriey from a map while iteration it to use an iterator
Iterator<Entry<Integer, String>> iterator = myMap.entrySet().iterator();
while(iterator.hasNext()) {
Entry<Integer, String> entry = iterator.next();
if (entry.getValue().contains("foo")) {
iterator.remove();
}
}
Since you have Map<Integer, String> I assume that the position you mean is the integer key, where you do something like myMap.put(1, "."), myMap.put(2, ".."), myMap.put(3, "...") and so on. In that case if you remove the mapping for the key 1 for example, the postion, i.e the mapping {1 : "."} will no longer exist in the map.
OK I got a codeable example that's pretty easy.
public class TestingThingsOut {
public static void main(String [] args) {
HashMap<Integer, String> myMap = new HashMap<Integer, String>();
myMap.put(123, "hello");
myMap.put(234, "Bye");
myMap.put(789, "asdf");
System.out.println(myMap); // it says:
{789=asdf, 234=Bye, 123=hello}
System.out.println(myMap.size()); // it says: "3"
for (Entry<Integer, String> entry : myMap.entrySet()) {
if (entry.getValue().contains("hello")) {
myMap.remove(entry);
}
}
System.out.println(myMap); // it says:
{789=asdf, 234=Bye, 123=hello}
System.out.println(myMap.size()); // it says: "3" again
}
}

Categories

Resources