Reputation: 49
I have an issue where using nested maps might not be the ideal solution , but need some feedback
Here is the generics structure that exists, where the fruit, vegetable, toys are keys ina map which in turn have another map associated where fresh, notfresh, rotten are keys of Map "b"
private Map<String, Commodity> Comm = new HashMap<String, Commodity>();
for (Map.Entry<String, Map<String, Object>> e : this.entrySet()) {
Comm.put(e.getKey(), getCommodity(e.getValue(), e.getKey()));
}
private Commodity getCommodity(Map<String, Object> m, String section) {
return new Commodity(m, section);
}
Fruit=> Fresh=>object
notFresh=>object
rotten=>object
Vegetable=> fresh=> object
notfresh=>object
rotten=>object
Toys=> fresh=>object
notfresh=>object
rotten=>object
However, i need to introduce another key called "season" where if the season is mentioned for a commodity, then the commodity comes under teh season otherwise stays as mentioned previously.
i.e
Fruit=> winter =>Fresh=>object
notFresh=>object
rotten=>object
Vegetable=> fresh=> object
notfresh=>object
rotten=>object
Toys=> summer => fresh=>object
notfresh=>object
rotten=>object
So in this case, fruits and toys have a season mentioned , in that case, it needs to look under winter for fruits and summer for toys. How can i acheive this complex map structure in java
Upvotes: 0
Views: 164
Reputation: 170
Maybe you could use an object to express the key of the map. The java HashMap use the hashCode
of the object for fast comparison - it fallback on equals
when the key collide (@see HashMap
.getEntry(Object key)).
class Key {
Item item; // fruit, toys or vegetable
Season season; // an enum for the season
// Constructor
public int hashCode()
{
int hash = 1;
hash *= 31 + item.hashCode();
hash *= 31 + season.hashCode();
return hash;
}
public boolean equals(Object obj)
{
return false; // implementing the equals too
}
}
Map<Key, Commodity> store = new HashMap<>();
store.put(
new Key(new Item("Fruit"), Season.FRESH),
new Commodity("asd")
);
store.put(
new Key(new Item("Fruit"), Season.NOT_FRESH),
new Commodity("qwe")
);
store.put(
new Key(new Item("Vegetable"), Season.ROTTEN),
new Commodity("zxc")
);
Upvotes: 1
Reputation: 198
Like Thomas said, this is not the ideal solution. However, just for the sake of testing it, here you go:
I guess I understood the structure correctly. If not please suggest.
Map<String, Map<String, Map<String,Commodity>>> root = new HashMap<String, Map<String,Map<String,Commodity>>>();
Map<String, Commodity> leaf = new HashMap<String, Commodity>();
leaf.put("fresh", new Commodity("name1", "type1"));
leaf.put("notFresh", new Commodity("name2", "type2"));
leaf.put("rotten", new Commodity("name3", "type3"));
Map<String, Map<String,Commodity>> mid = new HashMap<String, Map<String,Commodity>>();
mid.put("summer", leaf);
mid.put("winter", leaf);
root.put("vegetable", mid);
root.put("fruit", mid);
for (Entry<String, Map<String, Map<String, Commodity>>> middle: root.entrySet()) {
Map<String, Map<String,Commodity>> midVal= middle.getValue();
System.out.println("Type: "+ middle.getKey());
for (Entry<String, Map<String, Commodity>> leaves : midVal.entrySet()) {
Map<String,Commodity> leafVal = leaves.getValue();
System.out.println("Season: " + leaves.getKey());
for (Entry<String, Commodity> leafValNames : leafVal.entrySet()) {
System.out.println("key: "+ leafValNames.getKey() + "value: " + leafValNames.getValue());
}
}
}
}
This outputs
Type: fruit
Season: winter
key: rottenvalue: test.Commodity@8def646
key: freshvalue: test.Commodity@8def63c
key: notFreshvalue: test.Commodity@8def641
Season: summer
key: rottenvalue: test.Commodity@8def646
key: freshvalue: test.Commodity@8def63c
key: notFreshvalue: test.Commodity@8def641
Type: vegetable
Season: winter
key: rottenvalue: test.Commodity@8def646
key: freshvalue: test.Commodity@8def63c
key: notFreshvalue: test.Commodity@8def641
Season: summer
key: rottenvalue: test.Commodity@8def646
key: freshvalue: test.Commodity@8def63c
key: notFreshvalue: test.Commodity@8def641
The map looks like:
root =
{vegetable={winter={rotten=test.Commodity@8df1515, fresh=test.Commodity@8df150b, notFresh=test.Commodity@8df1510}, summer={rotten=test.Commodity@8df1515, fresh=test.Commodity@8df150b, notFresh=test.Commodity@8df1510}}}
mid =
{winter={rotten=test.Commodity@8df1515, fresh=test.Commodity@8df150b, notFresh=test.Commodity@8df1510}, summer={rotten=test.Commodity@8df1515, fresh=test.Commodity@8df150b, notFresh=test.Commodity@8df1510}}
leaf =
{rotten=test.Commodity@8df1515, fresh=test.Commodity@8df150b, notFresh=test.Commodity@8df1510}
Upvotes: 0
Reputation: 31605
You are right it "might not be the ideal solution". Maps are mechanism to hold a key and a value. A simple mapping if you want so. They are not made to build complicated data structures as you are trying to do. As you see by yourself, it gets very complicated and strange. So do not do this!
Make your own classes instead. Classes are the Java-way to make data structures. First, make a sketch how your data looks:
shop
)Correct me if I am wrong, but that is how I understood your question. If I am wrong, you can correct the details by your own.
Now we have 5 bullet points and we can make 5 classes out of them. I do it without getters and setters to keep it short:
class Shop {
List<Category> categories;
}
class Category {
String name;
List<Season> seasons;
}
class Season {
String name;
List<Products> products;
}
class Product {
String name;
boolean isRotten;
}
Now you can use this to put you shop together:
Shop myShop = new Shop();
Category toys = new Category();
Category fruits = new Category();
myShop.categories.add(toys);
myShop.categories.add(fruits);
Season summer = new Season();
fruits.seasons.add(summer);
Product apple = new Product();
Product pineapple = new Product();
Product banana = new Product();
summer.products.add(apple);
summer.products.add(pineapple);
summer.products.add(banana);
banana.isRotten = true;
Note:
Upvotes: 1