I am trying to create a dictionary type record, that holds for example key="Book name" and value= (key="price": $250, key="qty": 10). What would be the easiest way to achieve this is Java ? I have tried by creating a separate class object for they Value.
public class book_info {
int price = 0;
int qty = 0;
public void book_info(int qty, int price){
this.qty = qty;
this.price = price;
}
}
and creating a HashMap instance;
Map <String, book_info> items = new HashMap<String, book_info>();
items.put("Book1", new book_info(600, 20));
items.put("Book2", new book_info(200, 30));
items.put("Book3", new book_info(100, 50));
This works fine but is there any other alternate way by NOT using a separate class object, instead by just adding multiple key-value pairs in the initialization of HashMap like this;
Map <String, <<String, Integer>,<String, Integer>>> items = new HashMap<String, <<String, Integer>,<String, Integer>>>();
your question was probably already been answered, what your trying to do is use an object as the maping key, so instead of having [key, object] you want to have [object1, object2] and each object can be a map of which at the end will make them [[key1, value1][key2, value2]] for more details on using objects as keys see answer:
Using an instance of an object as a key in hashmap, and then access it with exactly new object?
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);
}
}
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.
I am trying to add hashmaps to array list.
But the map(completeEntrie) is overriding the previous values when I am trying to add more than one value to arraylist(listOfCompleteEntries)
public class MapExample {
public static void main(String a[]) {
ArrayList listOfCompleteEntries = new ArrayList();
Map<String, String> completeEntrie = new HashMap<String, String>();
for (int i = 0; i < 3; i++) {
completeEntrie.put("KEY_NAME", "Number:" + i);
System.out.print(completeEntrie.toString());
listOfCompleteEntries.add(completeEntrie);
System.out.println(listOfCompleteEntries.toString());
}
System.out.println(listOfCompleteEntries.toString());
}
}
Output for the above code is
{KEY_NAME=Number:0}[{KEY_NAME=Number:0}]
{KEY_NAME=Number:1}[{KEY_NAME=Number:1}, {KEY_NAME=Number:1}]
{KEY_NAME=Number:2}[{KEY_NAME=Number:2}, {KEY_NAME=Number:2}, {KEY_NAME=Number:2}]
[{KEY_NAME=Number:2}, {KEY_NAME=Number:2}, {KEY_NAME=Number:2}]
But i want the output to be like this
{KEY_NAME=Number:0}[{KEY_NAME=Number:0}]
{KEY_NAME=Number:1}[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}]
{KEY_NAME=Number:2}[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}, {KEY_NAME=Number:2}]
[{KEY_NAME=Number:0}, {KEY_NAME=Number:1}, {KEY_NAME=Number:2}]
Also please explain why is this map overriding the previous map in arraylist.
Thanks for your help.
Despite the irrelevant title, you need to construct a new map instance for each unique entry you want to add to the array list. Without this, you are modifying the same map instance.
I have to rank the teams in the array "names" (below) in order of who won the most games. If two teams won the same amount of games then I have to compare the wins of the teams that beat them. The code I have so far is below.
The full problem statement is given here: http://www.cs.duke.edu/csed/newapt/tournamentrank.html
So I want to use the comparator recursively. How can the Comparator can have access to the original data? I tried creating a Team class that takes a variable of the same class for the team that beat it, but that clearly doesn't work. Stuck here, please help!
public class TournamentRanker implements Comparator<String>{
public class Team {
String name;
Integer wins;
Team beatEm;
}
//HOW TO make maps visible to comparator?
public String[] rankTeams(String[] names, String[] lostTo) {
//map all teams to number of wins & to team that beat them
ArrayList<String> teams = new ArrayList<String>();
HashMap<String, Integer> Teamwins = new HashMap<String, Integer>();
HashMap<String, String> Whobeat = new HashMap<String, String>();
for(int x=0; x<names.length; x++)
{
if(!teams.contains(names[x]))
teams.add(names[x]);
if(!Teamwins.containsKey(names[x]))
Teamwins.put(names[x], 0);
Whobeat.put(names[x], lostTo[x]);
if(!Teamwins.containsKey(lostTo[x]) && !lostTo[x].equals(""))
Teamwins.put(lostTo[x], 0);
if(!lostTo[x].equals(""))
Teamwins.put(lostTo[x], (Teamwins.get(lostTo[x])+1));
}
for(String s: names)
{
Integer wins = Teamwins.get(s);
Team beatEm = new Team(Whobeat.get(s), Teamwins.get(Whobeat.get(s)), ????)
}
//SORT list & turn into ARRAY
Comparator<String> comp = new TournamentRanker();
Collections.sort(teams, comp);
String [] sortedTeams = new String[teams.size()];
return teams.toArray(sortedTeams);
}
//NEED to use compareTo***?? OTHER strategy????
//USE COMPARTOR - how to access all the data?
public int compare(String team1, String team2){
}
}
To make the maps visible, I suggest making the Comparator an inner class of TournamentRanker, and making the maps instance members of the TournamentRanker class, as follows:
public class TournamentRanker {
public class Team {
String name;
Integer wins;
Team beatEm;
}
// Map all teams to number of wins & to team that beat them
ArrayList<String> teams = new ArrayList<String>();
HashMap<String, Integer> Teamwins = new HashMap<String, Integer>();
HashMap<String, String> Whobeat = new HashMap<String, String>();
public String[] rankTeams(String[] names, String[] lostTo) {
TeamComparator teamComparator = new TeamComparator();
// Use teamComparator to sort teams.
...
}
private TeamComparator implements Comparator<String> {
public int compare(String team1, String team2){
// This function can now access the maps.
// Perform the comparison here.
...
}
}
}
If your goal is to write an object-oriented program, I would structure it as follows:
A Game class containing references to the two teams that played the game, and each team's score.
A Team class containing a Map of games played (Game objects) indexed by opposing team ID. If two teams can meet more than once than you'll need a "multi-map" that allows more than one value object per key.
A Tournament object containing both the Team instances (probably a Map indexed by team name) and Game objects (another Map indexed by some unique key of your choosing).
In your comparator, you can compare two teams' win-loss record, and in case of ties look at each team's individual games.