Store / unset multiple values with same key in HashMap - java

I am working with on line store project. At the moment I am trying to add possibility to add products to the shopping cart, no matter if user is logged in or not. I am using session bean method to do it.
#Inject ShoppingCartSessionBean shoppingCartSessionBean;
#POST
public boolean addToCart(#PathParam("productid") int newProductId, #PathParam("qu") int newProductQuantity) {
shoppingCartSessionBean.setCartItems(newProductId);
shoppingCartSessionBean.setProductQuantity(newProductQuantity);
return true;
}
I would like to store id's in hash map. However, at the moment I can set only one id for my setter method.
#Stateful
#SessionScoped
public class ShoppingCartSessionBean implements Serializable{
HashMap<Integer, Integer> newmap = new HashMap<Integer, Integer>();
public int addToHashMap() {
return array of productId's.
}
private static final long serialVersionUID = -5024959800049014671L;
private int productId;
private int productQuantity;
//getters and setters
Map<Integer, ShoppingCartSessionBean> hm = new HashMap<Integer, ShoppingCartSessionBean>();
Later I am using entity manager to check which id's / id were set and send back all information about that id to the user. I am not storing all values in session bean because of space issues.
Query q = em.createQuery("SELECT c FROM Items c WHERE c.productId = :itemid");
q.setParameter("itemid", shoppingCartSessionBean.addToHashMap());
So I have a few questions:
Is it good choice to store such information in hash map? Or should I use cookies instead?
How my addToHashmap method should look like to store multiple id's in hash map? (I tried a simply int[] array = {123, 456} to print out using my entity manager, however I got JSON error...).
What is the best way to remove / unset such information from hash map?
I hope my information is clear, if you are missing something - let me now.

Point 2 and 3. You need to check if there is a hash collision, in positive case you need to treat it. Look the code below.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class HashMapTest {
private static HashMap<String, List<String>> map = new HashMap<String, List<String>>();
public static void insert(String key, String value){
List<String> list = map.get(key);
if (list == null){
list = new ArrayList<String>();
map.put(key, list);
}
list.add(value);
}
public static void main(String[] args){
insert("10", "V1");
insert("10", "V2");
insert("20", "V3");
insert("20", "V4");
insert("30", "V5");
List<String> values10 = map.get("10");
System.out.println(values10);
List<String> values20 = map.get("20");
System.out.println(values20);
List<String> values30 = map.get("30");
System.out.println(values30);
}
}

Related

Retrieving nested key:value pairs in Java

I am wondering how to build a nested Map and then retrieve the nested key:value pairs. This is how I created the map to be nested.
//Create List of Nested HashMaps
List<Map> nestedMap = new ArrayList<>();
nestedMap.add(building3Map);
nestedMap.add(building31Map);
nestedMap.add(buildingHFTFMap);
System.out.println("The nested map is: " + nestedMap);
This is the system output for the following code:
The nested map is: [{buildingname=[Building 3], buildingid=[3]}, {buildingname=[Building 31], buildingid=[1]}, {buildingname=[HFTF], buildingid=[4]}]
This is correct as I want a list of maps. But the next step is what is confusing to me. When I try to build the outer layer Map as below:
HashMap<String, List<Map>> queryMap = new HashMap<>();
queryMap.put("buildings", nestedMap);
System.out.println(queryMap.get("buildings.buildingid"));
I get a system output of null when attempting the .get("buildings.buildingid") method. Ideally, I need the output to look like this:
[[3, 1, 4]]
Where it returns all values with a key of "buildings.buildingid" in an array. I am new to coding so please let me know if I'm making any fundamental errors and how I can create a nested Map where I can access the inner layer or if there is another method I should be using.
I think you are making it way too complicated than it should be. you can store your data in a simple map where the ids are the keys for example and the names are the values. So you only need to read the keys or the values from the map to get your result.
Map<Integer, String> myMap = new HashMap<>();
myMap.put(3, "Building 3");
myMap.put(31, "Building 31");
myMap.put(4, "HFTF");
System.out.println(myMap.keySet());
System.out.println(myMap.values());
However, Java is an object-oriented language. If it makes sense for your use case you might want to create a custom class "Building" instead of frantically trying to store your data in nested data structures. See below for an example of how it might look using a custom class:
import java.util.ArrayList;
import java.util.List;
public class Example {
public static void main(String args[]) {
List<Building> buildings = new ArrayList<>();
buildings.add(new Building(3, "Building 3"));
buildings.add(new Building(31, "Building 31"));
buildings.add(new Building(4, "HFTF"));
List<Integer> buildingIds = new ArrayList<>();
buildings.forEach(building -> buildingIds.add(building.getBuildingId()));
List<String> buildingNames = new ArrayList<>();
buildings.forEach(building -> buildingNames.add(building.getBuildingName()));
System.out.println(buildingIds);
System.out.println(buildingNames);
}
public static class Building {
int buildingId;
String buildingName;
public Building(final int buildingId, final String buildingName) {
this.buildingId = buildingId;
this.buildingName = buildingName;
}
public int getBuildingId() {
return buildingId;
}
public void setBuildingId(final int buildingId) {
this.buildingId = buildingId;
}
public String getBuildingName() {
return buildingName;
}
public void setBuildingName(final String buildingName) {
this.buildingName = buildingName;
}
}
}
queryMap.get("buildings.buildingid") returns null, because queryMap only contains a value under the key
buildings. A HashMap can only access the value using the same key it was stored under. The key and the value is not processed in any further way.
A simple alternative could be
queryMap.get("buildings").stream() // Create a Stream<Map>
.map(building -> building.get("buildingid")) // Create Stream<String> by extracting the buildingid values.
.collect(Collectors.toList()); // Collect Stream into a List<String> which contains the buildingid's
If you don't like this solution you could take a deeper look into property expressions, and write your own map implementation that can resolve these expressions. But it will be a lot of work to get it working correctly...

How to use HashMap when Json file has same key value

My json file looks like this [actually it has more, I am just putting 2 blocks for example]
[{
"answerValue": "2021-02-01",
"parentId": "Policy",
"instance": 1,
"fieldId": "PolicyEffectiveDate"
},
{
"answerValue": "2012",
"parentId": "Insured",
"instance": 1,
"fieldId": "DateBusinessStarted"
}
]
I want to store them in a HashMap and print them.
public void MapCheck() {
Map<String, Object> dataMap = new HashMap<>();
List<Map> lstMap = new ArrayList<>();
dataMap.put("answerValue:", "2021-02-01");
dataMap.put("parentId:", "Policy");
dataMap.put("instance:", 1);
dataMap.put("fieldId:", "PolicyEffectiveDate");
lstMap.add(dataMap);
dataMap.put("answerValue:", "Assurestart LLC");
dataMap.put("parentId:", "Insured");
dataMap.put("instance:", 1);
dataMap.put("fieldId:", "Business_Name");
lstMap.add(dataMap);
System.out.println(lstMap);
}
public static void main(String[] args) {
Test t = new Test();
t.MapCheck();
}
}
Expected: I wanted it to print
[{parentId:=Policy, fieldId:=PolicyEffectiveDate, answerValue:=2021-02-01, instance:=1}, {parentId:=Insured, fieldId:=Business_Name, answerValue:=Assurestart LLC, instance:=1}]
Actual: It is printing, the last value twice.
[{parentId:=Insured, fieldId:=Business_Name, answerValue:=Assurestart LLC, instance:=1}, {parentId:=Insured, fieldId:=Business_Name, answerValue:=Assurestart LLC, instance:=1}]
How can I make it print 2 different values? Thanks in advance for your time and ideas.
You should create a new map for the second entry instead of overwriting the first entry’s values. Add
dataMap = new HashMap<>();
After adding the first entry to the list.
You should create a new map for the second map in the list:
Map<String, Object> dataMap = new HashMap<>();
List<Map<String, Object>> lstMap = new ArrayList<>();
dataMap.put("answerValue:", "2021-02-01");
dataMap.put("parentId:", "Policy");
dataMap.put("instance:", 1);
dataMap.put("fieldId:", "PolicyEffectiveDate");
lstMap.add(dataMap);
dataMap = new HashMap<>(); // create a new map!
dataMap.put("answerValue:", "Assurestart LLC");
dataMap.put("parentId:", "Insured");
dataMap.put("instance:", 1);
dataMap.put("fieldId:", "Business_Name");
lstMap.add(dataMap);
That said, if you actually want to generate JSON, or read a JSON file, I recommend using a JSON serialisation/deserialisation library, such as GSON. That way, you can represent your data not as hash maps, but a class like this:
class MyObject {
private String answerValue;
private String parentId;
private int instance;
private String fieldId;
// getters & setters...
}
HashMap as you know is a data structure that works based on unique key and value pair property.
In the example above when you perform dataMap.put("answerValue:", "2021-02-01"); it saves the value for this key in the HashMap. However when you perform, dataMap.put("answerValue:", "Assurestart LLC"); the second time, it will override the value of "answerValue:" key as it already exists there.
A better approach is to create a new class that can contain all this data in it and then you can decide on a unique key to store this data in. Thus your values will be an object that contains this entire block of data.
For example,
public class MyData {
private String answerValue;
private String parentId;
private Integer instance;
private String fieldId;
//Setters and getters
...
}

alternative data structure to map in java for storing below daata [duplicate]

I have a map as shown below in which there is a key and values is of type List:
Map<String, List<String> newdatamap = new HashMap<>();
map.put ("RtyName", Arrays.asList("wpn", "wpfnb", "dgeft", "xbthy"));
map.put ("rtyRate", Arrays.asList("dd", "ww", "trrty", "httyure"))
I'd like to add another map over the previous map, such that there is a key and its value will be the above map. Is this the correct data structure, and how do we implement it?
I want something like this shown below
Key Value
B1 RtyName ----> "weepn", "weepfnb", "eedgeft", "xbteehy"
rtyRate ----->"deed", "ww", "terrty", "hteetyure"
B2 RtyName ----> "SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"
rtyRate ----->"WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"
As shown above, only a new key is been introduced to the map, and its value is the previous map.
so it is like a Map<String, Map<String, List<String>>> whis becomes a complex data structure can i organise the data structure as
for example one class containing a Map, so it will be like
Map<B1 , RtyName>
Map<B2 ,rtyRate>
and payer nae contain list of values such as
RtyName ----> "SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"
rtyRate ----->"deed", "ww", "terrty", "hteetyure"
so in the above structure complexity will be low since at the end for B1 i have to search key that wiil be RtyName and against payer name further i have to search values which will be "wpn", "wpfnb", "dgeft", "xbthy"
please advise whheteher map will be best or is there any other better data structure also to obtain this .
one data structure coming in my mind is of Guava's Table
final Table<String, String, List<String>> values = HashBasedTable.create();
values.put("B1", "RtyName", Lists.newArrayList("weepn", "weepfnb", "eedgeft", "xbteehy"));
System.out.println(values.get("B1", "RtyName")); // prints the list
My objective is that any data structure I can have in which against B1 I will get Rtyname and for Rtyname I will get possible list of values
I would do this:
Map<Integer, List<String>> dataMap = new HashMap<>();
dataMap.put("B1".hashCode()+"RtyName".hashCode(), Arrays.asList("weepn", "weepfnb", "eedgeft", "xbteehy"));
dataMap.put("B1".hashCode()+"rtyRate".hashCode(), Arrays.asList("deed", "ww", "terrty", "hteetyure"));
dataMap.put("B2".hashCode()+"RtyName".hashCode(), Arrays.asList("SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"));
dataMap.put("B2".hashCode()+"rtyRate".hashCode(), Arrays.asList("WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"));
Which would represent:
B1, RtyName ----> "weepn", "weepfnb", "eedgeft", "xbteehy"
B1, rtyRate ----->"deed", "ww", "terrty", "hteetyure"
B2, RtyName ----> "SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"
B2, rtyRate ----->"WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"
Note that hashCode is just a convient function from the String class that meets my needs. You could roll your own that returns a String key (or really anything else) if you preferred.
Actually since your original method didn't require an order independent function, you could really even concatenate the String keys to use as a new key:
dataMap.put("B1"+"RtyName", Arrays.asList(/*your list here*/));
This is a little less convenient (and not as "good" programmatically) than the first method, but still much better than nesting Map classes. (And makes keys much easier to recognize when outputted than hashCode.)
Two-way Mapping
Values as Keys
If you want each List value to map to keys as well as the other way around, you need a second Map:
Map<List<String>, String> valueMap = new HashMap<>(); //New map for value->key
for(String key: dataMap.keySet()) //Get all keys
valueMap.put(dataMap.get(key), key); //Create mapping value->key
Each Item in Value as a Key
If you want each String item in the values list to map to keys as well as the other way around, you need a second Map:
Map<String, String> itemMap = new HashMap<>(); //New map for item->key mapping
for(String key: dataMap.keySet()) //Get all keys and iterate through
for(String item: dataMap.get(key)) //For each item in your value list
itemMap.put(item, key); //Create new mapping item->key
As you asked for it:
You simply define a class, ABC in this case as you've suggested that name, which holds two lists, the RtyName and the rtyRate list:
public class ABC {
private List<String> RtyName;
private List<String> rtyRate;
public ABC(List<String> RtyName, List<String> rtyRate) {
setRtyNames(RtyName);
setRtyRates(rtyRate);
}
public void setRtyNames(List<String> RtyName) {
this.RtyName = RtyName;
}
public List<String> getRtyNames() {
return this.RtyName;
}
public void setRtyRates(List<String> rtyRate) {
this.rtyRate = rtyRate;
}
public List<String> getRtyRates() {
return this.rtyRate;
}
}
Once this class is ready, you can change your map definition to:
Map<String, ABC> newdatamap = new HashMap<>();
And assign new values to it similar as you already did before - instead of nesting those lists in a further map and putting this map into the outer map though, you create a new instance of ABC, provide the two lists as input parameter and put the resulting ABC object into the map (formally the outer map):
List<String> RtyName = Arrays.asList("wpn", "wpfnb", "dgeft", "xbthy");
List<String> rtyRate = Arrays.asList("dd", "ww", "trrty", "httyure");
newdatamap.put("B1", new ABC(RtyName, rtyRate));
You could also assign those lists directly as input-parameters:
newdatamap.put("B2", new ABC(Arrays.asList("SSSweepn", "wpefSSSnb", "GGeGdgeft", "xbteYYYYhy"),
Arrays.asList("WWded", "wTeTYw", "YYYYtrerty", "IIIehttyure"));
An entry is now simply retrieved on calling get(String) as you already used to do:
ABC data = newdatamap.get("B1);
You can also retrieve one of the lists directly like:
List<String> RtyNames = newdatamap.get("B1").getRtyNames();
In my opinion this is way easier to manage and to read at the same time. On top of that, you gain also runtime-saftiness as you do not run into eventual typing errors for RtyName or rtyRate.
Update for redesign
If RtyName entries and rtyRate entries always go hand in hand, f.e. wpn is the name and dd is the assigned rate, grouping those fields together would make sense. Therefore you could refactor your code to furthermore reduce one list and introduce a new class:
public class RtyEntry {
private String name;
private String rate;
public RtyEntry(String name, String rate) {
setName(name);
setRate(rate);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setRate(String rate) {
this.rate = rate;
}
public String getRate() {
return this.rate;
}
}
If you now change ABC to only contain one list of RtyEntry objects like this:
public class ABC {
private List<RtyEntry> rtyEntries;
public ABC(List<RtyEntry> rtyEntries) {
this.rtyEntries = rtyEntries;
}
public ABC() {
this.rtyEntries = new ArrayList<>();
}
public void setRtyEntries(List<RtyEntry> rtyEntries) {
this.rtyEntries = rtyEntries;
}
public List<RtyEntry> getRtyEntries() {
return this.rtyEntries;
}
// convenience methods
public void addRtyEntry(RtyEntry entry) {
this.rtyEntries.add(entry);
}
}
The creation would now change to:
RtyEntry entry1 = new RtyEntry("wpn", "dd");
List<RtyEntry> entries = Arrays.asList(entry1, ...);
newdatamap.put("B1", new ABC(entries));
You can then also assign new entries like that:
newdatamap.get("B1").addRtyEntry(new RtyEntry("wpfnb", "ww"));
Retrieving entries also changed to the refactoring:
ABC data = newdatamap.get("B1");
List<RtyEntry> entries = data.getRtyEntries();
for (RtyEntry entry : entries) {
System.out.println(entry.getName() + " has a rate of: " + entry.getRate());
}
Of course you can also retrieve the list directly via:
List<RtyEntry> entries = newdatamap.get("B1").getRtyEntries();
as before.

key value pair implementation in java?

Is there something like a KeyValuePair in Java?
I have a Very long list of elements of the following class:
public class Foo {
int id;
Set<String> items;
}
which is stored here:
LinkedList<Foo> myList;
each time I search for a item, I iterate over the list and search for the Item, but this takes to much time.
I want to do something like this:
myList.get(123) => items of the Foo with id = 123
You can use Map in Java for that purpose. It will allow key, value pairs.
Map<Integer,Set<String>> map = new HashMap<Integer,Set<String>>();
Adding item to map
Set<String> set = new HashSet<String>();
set.add("ABC");
set.add("DEF");
map.put(123,set);
Getting item from map
map .get(123) will give Set<String> associated with id 123
Try some impelementation of java.util.Map.
More info: here
I think the MultiMap<Integer,String> is suitable in your case.
Guava MultiMap
Apache commons MultiMap
you would need a so called MultiMap, java dont has that by default, but you always can use a Map for that purpose.
Try using a HashMap<Integer, Set<String>>
import java.util.*;
class temp{
public static void main(String[] args){
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1,"anand");
map.put(2,"bindu");
map.put(3,"cirish");
System.out.println(1+" = "+map.get(1));
System.out.println(2+" = "+map.get(2));
System.out.println(3+" = "+map.get(3));
Map<String,Integer> map1 = new HashMap<String,Integer>();
map1.put("anand",1);
map1.put("bindu",2);
map1.put("cirish",3);
System.out.println("anand = "+map1.get("anand"));
System.out.println("bindu = "+map1.get("bindu"));
if(map1.get("cirish") != null){
System.out.println("cirish = "+map1.get("cirish"));
}
if(map1.get("dinesh") != null){
System.out.println("cirish = "+map1.get("dinesh"));
}
}
}

Combining two HashMaps into a third

Let's say I have an object of each class below, and I put each object in a hashmap where IDnumber is the key in both maps.
class1 {
int IDNumber = 123; //same person as class2
String name = John;
String company = Intel;
class2 {
int IDNumber = 123; //same person as class1
int income = 500;
int workYears = 3;
}
HashMap<Integer, class1> one = new Hashmap<Integer, class1>();
HashMap<Integer, class2> two = new HashMap<Integer, class2>();
Now, how can I mash these two HashMaps into a third HashMap so that I can have the key IDnumber, and the values name, company, income, and workyears?
You can not do that. You have two different classes, and java is not going to auto-magically make them one.
You could create a new third class to merge the info:
public Class3 {
public Class3(Class1 class1, Class2 class2){
//pull the info you want from each into variables in this class
}
}
Then loop through your map to get the entries, creating new Class3 instance for each and place them in a new HashMap<Integer, Class3>.
//gets the keys from the hashmap
Set<Integer> keys = one.keySet();
//merge the keys from the second hashmap
keys.addAll(two.keySet());
//new hashmap
Map<Integer, Class3> newMap = new HashMap<Integer, Class3>();
for (Integer key : keys){
//create new instance and place it in the map
newMap.put(key, new Class3(one.get(key), two.get(key));
}
Create a 3rd class called Combined in one of these 2 ways:
Combined {
class1 info1;
class2 info2;
}
Or, better:
Combined {
int IDNumber = 123;
String name = John;
String company = Intel;
int income = 500;
int workYears = 3;
}
Create a 3rd (empty) HashMap
Now iterate over all elements in the first HashMap you had before
For each entry, look up the same key in the 2nd HashMap:
If it is found, combine the information from these 2 entries and add it as a single entry of instance Combined to the 3rd HashMap. Then remove both of these entries from both HashMaps one and two.
If it is not found, then create a Combined instance anyway based on the entry in HashMap one and just set the unavailable information that would have come from a corresponding entry from HashMap two to null. Remove the entry from HashMap one.
Now the 1st HashMap should be empty. Iterate HashMap two to find any entries that did not have a corresponding ID in HashMap one. Add them to the 3rd HashMap as above.
You can't store multiple values (i.e. Class1 and Class2 in your case) with the same key in a java.util.Map. What you want is a Multimap. Guava has an implementation for this. The one you are looking for is ArrayListMultimap.
You need to make a new class which is a mashup of class1 and class2 along with a new Map for it. Each time you put something in one and 'two' you make a new mashup containing both objects and put it into three.
As your data structure is not solit you should use some adapter/wraper
public class UserClassWrapper {
private final UserClass1 class1;
private final UserClass2 class2;
UserWithDetail(UserClass1 class1, UserClass2 class2) {
//Check preconditions as class1 and class2 must not be null and have equal id
this.class1 = class1;
this.class2 = class2;
}
}
Then in your code you can declare a map:
private Map<Integer,UserClassWrapper> userClassWrappeMap = new HashMap<>();
You can use an ArrayList to create an HashMap with multiple of values for one key
ArrayList<> list = new ArrayList();
/* populate your list here with two class having the same ID */
HashMap<Integer, List> three = new Hashmap();
/* Put list on the Hashmap */
/* Redo the operation with another ID */
But it's not very optimized, if you aren't obliged to have an HashMap at final, use directly a multiHashMap: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/MultiHashMap.html
Are you expecting this kind of arrangment
class class1 {
int IDNumber = 123; //same person as class2
String name = "John";
String company = "Intel";
}
class class2 {
int IDNumber = 123; //same person as class1
int income = 500;
int workYears = 3;
}
public class MyData{
public static void main(String arg[]){
HashMap<Integer, class1> one = new HashMap<Integer, class1>();
HashMap<Integer, class2> two = new HashMap<Integer, class2>();
one.put(1, new class1());
two.put(2, new class2());
HashMap<Integer, Object> three = new HashMap<Integer, Object>();
three.putAll(one);
three.putAll(two);
System.out.println(three);
}
}

Categories

Resources