I have a HashMap in Java, the contents of which (as you all probably know) can be accessed by
HashMap.get("keyname");
If a have a HashMap inside another HashMap i.e. a nested HashMap, how would i access the contents? Can i do this like this, inline:
HashMap.get("keyname").get("nestedkeyname");
Thank you.
You can do it like you assumed. But your HashMap has to be templated:
Map<String, Map<String, String>> map =
new HashMap<String, Map<String, String>>();
Otherwise you have to do a cast to Map after you retrieve the second map from the first.
Map map = new HashMap();
((Map)map.get( "keyname" )).get( "nestedkeyname" );
You can get the nested value by repeating .get(), but with deeply nested maps you have to do a lot of casting into Map. An easier way is to use a generic method for getting a nested value.
Implementation
public static <T> T getNestedValue(Map map, String... keys) {
Object value = map;
for (String key : keys) {
value = ((Map) value).get(key);
}
return (T) value;
}
Usage
// Map contents with string and even a list:
{
"data": {
"vehicles": {
"list": [
{
"registration": {
"owner": {
"id": "3643619"
}
}
}
]
}
}
}
List<Map> list = getNestedValue(mapContents, "data", "vehicles", "list");
Map first = list.get(0);
String id = getNestedValue(first, "registration", "owner", "id");
Yes.
See:
public static void main(String args[]) {
HashMap<String, HashMap<String, Object>> map = new HashMap<String, HashMap<String,Object>>();
map.put("key", new HashMap<String, Object>());
map.get("key").put("key2", "val2");
System.out.println(map.get("key").get("key2"));
}
If you plan on constructing HashMaps with variable depth, use a recursive data structure.
Below is an implementation providing a sample interface:
class NestedMap<K, V> {
private final HashMap<K, NestedMap> child;
private V value;
public NestedMap() {
child = new HashMap<>();
value = null;
}
public boolean hasChild(K k) {
return this.child.containsKey(k);
}
public NestedMap<K, V> getChild(K k) {
return this.child.get(k);
}
public void makeChild(K k) {
this.child.put(k, new NestedMap());
}
public V getValue() {
return value;
}
public void setValue(V v) {
value = v;
}
}
and example usage:
class NestedMapIllustration {
public static void main(String[] args) {
NestedMap<Character, String> m = new NestedMap<>();
m.makeChild('f');
m.getChild('f').makeChild('o');
m.getChild('f').getChild('o').makeChild('o');
m.getChild('f').getChild('o').getChild('o').setValue("bar");
System.out.println(
"nested element at 'f' -> 'o' -> 'o' is " +
m.getChild('f').getChild('o').getChild('o').getValue());
}
}
As others have said you can do this but you should define the map with generics like so:
Map<String, Map<String, String>> map = new HashMap<String, Map<String,String>>();
However, if you just blindly run the following:
map.get("keyname").get("nestedkeyname");
you will get a null pointer exception whenever keyname is not in the map and your program will crash. You really should add the following check:
String valueFromMap = null;
if(map.containsKey("keyname")){
valueFromMap = map.get("keyname").get("nestedkeyname");
}
Yes, if you use the proper generic type signature for the outer hashmap.
HashMap<String, HashMap<String, Foo>> hm = new HashMap<String, HashMap<String, Foobar>>();
// populate the map
hm.get("keyname").get("nestedkeyname");
If you're not using generics, you'd have to do a cast to convert the object retrieved from the outer hash map to a HashMap (or at least a Map) before you could call its get() method. But you should be using generics ;-)
I prefer creating a custom map that extends HashMap. Then just override get() to add extra logic so that if the map doesnt contain your key. It will a create a new instance of the nested map, add it, then return it.
public class KMap<K, V> extends HashMap<K, V> {
public KMap() {
super();
}
#Override
public V get(Object key) {
if (this.containsKey(key)) {
return super.get(key);
} else {
Map<K, V> value = new KMap<K, V>();
super.put((K)key, (V)value);
return (V)value;
}
}
}
Now you can use it like so:
Map<Integer, Map<Integer, Map<String, Object>>> nestedMap = new KMap<Integer, Map<Integer, Map<String, Object>>>();
Map<String, Object> map = (Map<String, Object>) nestedMap.get(1).get(2);
Object obj= new Object();
map.put(someKey, obj);
I came to this StackOverflow page looking for a something ala valueForKeyPath known from objc. I also came by another post - "Key-Value Coding" for Java, but ended up writing my own.
I'm still looking for at better solution than PropertyUtils.getProperty in apache's beanutils library.
Usage
Map<String, Object> json = ...
public String getOptionalFirstName() {
return MyCode.getString(json, "contact", "firstName");
}
Implementation
public static String getString(Object object, String key0, String key1) {
if (key0 == null) {
return null;
}
if (key1 == null) {
return null;
}
if (object instanceof Map == false) {
return null;
}
#SuppressWarnings("unchecked")
Map<Object, Object> map = (Map<Object, Object>)object;
Object object1 = map.get(key0);
if (object1 instanceof Map == false) {
return null;
}
#SuppressWarnings("unchecked")
Map<Object, Object> map1 = (Map<Object, Object>)object1;
Object valueObject = map1.get(key1);
if (valueObject instanceof String == false) {
return null;
}
return (String)valueObject;
}
import java.util.*;
public class MyFirstJava {
public static void main(String[] args)
{
Animal dog = new Animal();
dog.Info("Dog","Breezi","Lab","Chicken liver");
dog.Getname();
Animal dog2= new Animal();
dog2.Info("Dog", "pumpkin", "POM", "Pedigree");
dog2.Getname();
HashMap<String, HashMap<String, Object>> dogs = new HashMap<>();
dogs.put("dog1", new HashMap<>() {{put("Name",dog.name);
put("Food",dog.food);put("Age",3);}});
dogs.put("dog2", new HashMap<>() {{put("Name",dog2.name);
put("Food",dog2.food);put("Age",6);}});
//dogs.get("dog1");
System.out.print(dogs + "\n");
System.out.print(dogs.get("dog1").get("Age"));
}
}
Example Map:
{
"data": {
"userData": {
"location": {
"city": "Banja Luka"
}
}
}
}
Implementation:
public static Object getValueFromMap(final Map<String, Object> map, final String key) {
try {
final String[] tmpKeys = key.split("\\.");
Map<String, Object> currentMap = map;
for (int i = 0; i < tmpKeys.length - 1; i++) {
currentMap = (Map<String, Object>) currentMap.get(tmpKeys[i]);
}
return currentMap.get(tmpKeys[tmpKeys.length - 1]);
} catch (Exception exception) {
return null;
}
}
Usage:
final Map<String, Object> data = new HashMap<>();
final Map<String, Object> userData = new HashMap<>();
final Map<String, Object> location = new HashMap<>();
location.put("city", "Banja Luka");
userData.put("location", location);
data.put("userData", userData);
System.out.println(getValueFromMap(data, "userData.location.city"));
Result:
Banja Luka
Process finished with exit code 0
I hit this discussion while trying to figure out how to get a value from a nested map of unknown depth and it helped me come up with the following solution to my problem. It is overkill for the original question but maybe it will be helpful to someone that finds themselves in a situation where you have less knowledge about the map being searched.
private static Object pullNestedVal(
Map<Object, Object> vmap,
Object ... keys) {
if ((keys.length == 0) || (vmap.size() == 0)) {
return null;
} else if (keys.length == 1) {
return vmap.get(keys[0]);
}
Object stageObj = vmap.get(keys[0]);
if (stageObj instanceof Map) {
Map<Object, Object> smap = (Map<Object, Object>) stageObj;
Object[] skeys = Arrays.copyOfRange(keys, 1, keys.length);
return pullNestedVal(smap, skeys);
} else {
return null;
}
}
Related
If I have class like this:
class MyObject {
public int myInt;
public String myString;
}
Is it possible to convert instance of this class to HashMap without implementing converting code?
MyObject obj = new MyObject();
obj.myInt = 1; obj.myString = "string";
HashMap<String, Object> hs = convert(obj);
hs.getInt("myInt"); // returns 1
hs.getString("myString"); // returns "string"
Does Java provide that kind of solution, or I need to implement convert by myself?
My Class has more than 50 fields and writing converter for each field is not so good idea.
With jackson library this is also possible
MyObject obj = new MyObject();
obj.myInt = 1;
obj.myString = "1";
ObjectMapper mapObject = new ObjectMapper();
Map < String, Object > mapObj = mapObject.convertValue(obj, Map.class);
You can use reflection for implementing this behavior. You can get all fields of the class you want to convert to map iterate over this fields and take the name of each field as key of the map. This will result in a map from String to object.
Map<String, Object> myObjectAsDict = new HashMap<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
Class<?> targetType = field.getType();
Object objectValue = targetType.newInstance();
Object value = field.get(objectValue);
myObjectAsDict.put(field.getName(), value);
}
}
Something like that will do the trick:
MyObject obj = new MyObject();
obj.myInt = 1; obj.myString = "string";
Map<String, Object> map = new HashMap<>();
// Use MyObject.class.getFields() instead of getDeclaredFields()
// If you are interested in public fields only
for (Field field : MyObject.class.getDeclaredFields()) {
// Skip this if you intend to access to public fields only
if (!field.isAccessible()) {
field.setAccessible(true);
}
map.put(field.getName(), field.get(obj));
}
System.out.println(map);
Output:
{myString=string, myInt=1}
You might consider using a map instead of a class.
Or have your class extend a map such as
public class MyObject extends HashMap<String, Object> {
}
If you don't want to use Reflection then you can use my trick. hope this may help for someone.
Suppose your class looks like this.
public class MyClass {
private int id;
private String name;
}
Now Override toString() method in this class. in Eclipse there is a shortcut for generating this method also.
public class MyClass {
private int id;
private String name;
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("MyClass [id=").append(id).append(", name=").append(name).append("]");
return builder.toString();
}
}
Now write a method inside this class that will convert your object into Map<String,String>
public Map<String, String> asMap() {
Map<String, String> map = new HashMap<String, String>();
String stringRepresentation = this.toString();
if (stringRepresentation == null || stringRepresentation.trim().equals("")) {
return map;
}
if (stringRepresentation.contains("[")) {
int index = stringRepresentation.indexOf("[");
stringRepresentation = stringRepresentation.substring(index + 1, stringRepresentation.length());
}
if (stringRepresentation.endsWith("]")) {
stringRepresentation = stringRepresentation.substring(0, stringRepresentation.length() - 1);
}
String[] commaSeprated = stringRepresentation.split(",");
for (int i = 0; i < commaSeprated.length; i++) {
String keyEqualsValue = commaSeprated[i];
keyEqualsValue = keyEqualsValue.trim();
if (keyEqualsValue.equals("") || !keyEqualsValue.contains("=")) {
continue;
}
String[] keyValue = keyEqualsValue.split("=", 2);
if (keyValue.length > 1) {
map.put(keyValue[0].trim(), keyValue[1].trim());
}
}
return map;
}
Now from any where in your application you can simply call this method to get your HashMap from the Object. Cheers
Updated approach using reflection:
public static <T> Map<String, String> parseInnerClass(T classInstance) {
LinkedHashMap<String, String> ret = new LinkedHashMap<>();
for (Field attr : classInstance.getClass().getDeclaredFields()) {
String attrValue = "";
attr.setAccessible(true);
try {
attrValue = attr.get(classInstance).toString();
} catch (IllegalAccessException | NullPointerException e) {
// Do not add nothing
}
ret.put(attr.getName(), attrValue);
}
return ret;
}
Is there a utility in java to de parameterize the object parameterized by Jquery param() method. I got the following code working for now( I can parse the returned map to a Json object). Don't know how robust it will be. Is there a util in java just like js one here
public class Util {
/**
* Deparameterize to original json form the query params coming from the jquery.param() method.
* #param query the query string key value(array of values if same key repeated) pairs.
* #return
*/
public static Map<String, Object> deParam(Map<String, String[]> query) {
Map<String, Object> map = new HashMap<>();
List<Map<String,Object>> toArray=new ArrayList<>();
for (String key : query.keySet()) {
//ex key $and[0][price][$lt]
String value=query.get(key)[0];
key = key.replace("]", "");
String[] split = key.split("\\[");
Map<String, Object> grandParent =null;
Map<String, Object> parent =map;
String parentName="root";
Map<String, Object> child = null;
String lastSkey=null;
for (String skey : split) {
Object me = parent.get(skey);
if(skey.matches("[0-9]+")){
//if array key
toArray.add(parent);
parent.put("parent",grandParent);
parent.put("myName", parentName );
}
if (me == null) {
child=new HashMap<>();
parent.put(skey, child);
grandParent=parent;
parent=child;
parentName=skey;
} else {
grandParent=parent;
parent = (Map<String, Object>) me;
parentName=skey;
}
lastSkey=skey;
}
if(value.matches("[0-9]+\\.?[0-9]+")){
Double numVal=new Double(value);
grandParent.put(lastSkey,numVal);
}else {
grandParent.put(lastSkey,value);
}
}
for (Map<String, Object> arrayMap : toArray) {
Map<String, Object> myParent = (Map<String, Object>) arrayMap.remove("parent");
String myName = (String) arrayMap.remove("myName");
if(myParent!=null&&myName!=null){
myParent.put(myName, arrayMap.values());
}else if(myName!=null && myName.equals("root")){
map.put("list", arrayMap.values());
}
}
return map;
}
}
I have a unit test that needs to check for a nested map value. I can get my assertion to work by pulling out the entry and matching the underlying Map, but I was looking for a clear way to show what the assertion is doing. Here is a very simplified test:
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasEntry;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
public class MapContainsMapTest {
#Test
public void testMapHasMap() {
Map<String, Object> outerMap = new HashMap<String, Object>();
Map<String, Object> nestedMap = new HashMap<String, Object>();
nestedMap.put("foo", "bar");
outerMap.put("nested", nestedMap);
// works but murky
assertThat((Map<String, Object>) outerMap.get("nested"), hasEntry("foo", "bar"));
// fails but clear
assertThat(outerMap, hasEntry("nested", hasEntry("foo", "bar")));
}
}
It seems the problem is the outer map is being compared using hasEntry(K key, V value) while what I want to use is hasEntry(Matcher<? super K> keyMatcher, Matcher<? super V> valueMatcher). I am not sure how to coerce the assertion to use the second form.
Thanks in advance.
If you only want to put Map<String, Object> as values in your outerMap adjust the declaration accordingly. Then you can do
#Test
public void testMapHasMap() {
Map<String, Map<String, Object>> outerMap = new HashMap<>();
Map<String, Object> nestedMap = new HashMap<String, Object>();
nestedMap.put("foo", "bar");
outerMap.put("nested", nestedMap);
Object value = "bar";
assertThat(outerMap, hasEntry(equalTo("nested"), hasEntry("foo", value)));
}
Object value = "bar"; is necessary for compile reasons. Alternatively you could use
assertThat(outerMap,
hasEntry(equalTo("nested"), Matchers.<String, Object> hasEntry("foo", "bar")));
If You declare outerMap as Map<String, Map<String, Object>> you don't need the ugly cast. Like this:
public class MapContainsMapTest {
#Test
public void testMapHasMap() {
Map<String, Map<String, Object>> outerMap = new HashMap<>();
Map<String, Object> nestedMap = new HashMap<>();
nestedMap.put("foo", "bar");
outerMap.put("nested", nestedMap);
assertThat(outerMap.get("nested"), hasEntry("foo", "bar"));
}
}
I would probably extend a new Matcher for that, something like that (beware, NPEs lurking):
class SubMapMatcher extends BaseMatcher<Map<?,?>> {
private Object key;
private Object subMapKey;
private Object subMapValue;
public SubMapMatcher(Object key, Object subMapKey, Object subMapValue) {
super();
this.key = key;
this.subMapKey = subMapKey;
this.subMapValue = subMapValue;
}
#Override
public boolean matches(Object item) {
Map<?,?> map = (Map<?,?>)item;
if (!map.containsKey(key)) {
return false;
}
Object o = map.get(key);
if (!(o instanceof Map<?,?>)) {
return false;
}
Map<?,?> subMap = (Map<?,?>)o;
return subMap.containsKey(subMapKey) && subMap.get(subMapKey).equals(subMapValue);
}
#Override
public void describeTo(Description description) {
description.appendText(String.format("contains %s -> %s : %s", key, subMapKey, subMapValue));
}
public static SubMapMatcher containsSubMapWithKeyValue(String key, String subMapKey, String subMapValue) {
return new SubMapMatcher(key, subMapKey, subMapValue);
}
}
Try like this :
assertThat(nestedMap).contains(Map.entry("foo", "bar"));
assertThat(outerMap).contains(Map.entry("nested", nestedMap));
I would like to know how can I iterate in a 2Dimensional HashMap? I am creating an Object TrueStringMap2D that does the following: It will be a map 2D, i mean 2 keys and one value.
But the iterator implemented here is not functional.. i didnt know how to redefine the Iterator method in TrueStringMap2D :S (if possible should be remove in the iterator() functional)
Anyone can help?
Thankyou very much!!
I'll reinterpret the question into something similar that I enjoy answering, and then hopefully the answer to that question is useful to you.
Here's the question I'll answer:
How do I write an iterator that iterates over all values in a Map<String, Map<String, String>>?
This is how I would solve it:
class TwoDimIterator implements Iterator<String> {
Iterator<Map<String, String>> outerIter;
Iterator<String> innerIter = Collections.<String>emptyList().iterator();
public TwoDimIterator(Map<String, Map<String, String>> twoDimMap) {
outerIter = twoDimMap.values().iterator();
advanceInner();
}
#Override
public boolean hasNext() {
return innerIter.hasNext();
}
#Override
public String next() {
String toReturn = innerIter.next();
advanceInner();
return toReturn;
}
private void advanceInner() {
while (!innerIter.hasNext()) {
if (!outerIter.hasNext()) {
innerIter = Collections.<String>emptyList().iterator();
return;
}
innerIter = outerIter.next().values().iterator();
}
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
Test code:
class Test {
public static void main(String[] args) {
// Create a map
Map<String, Map<String, String>> twoDimMap =
new HashMap<String, Map<String, String>>();
// Fill it
Map<String, String> innerA = new HashMap<String, String>();
innerA.put("1", "A1");
innerA.put("2", "A2");
Map<String, String> innerB = new HashMap<String, String>();
innerB.put("1", "B1");
innerB.put("2", "B2");
twoDimMap.put("A", innerA);
twoDimMap.put("B", innerB);
// Create an iterator for the values:
Iterator<String> twoDimIter = new TwoDimIterator(twoDimMap);
while (twoDimIter.hasNext())
System.out.println(twoDimIter.next());
}
}
Output:
A2
A1
B2
B1
I need a mapping from a list of keys to a value. I know I could write my own code like this:
Map<Person, Map<Daytime, Map<Food, Integer>>> eaten = ...;
Now I want to have some get and put methods like these:
Integer numberOfEggsIAteInTheMorning = eaten.get(me, morning, scrambledEggs);
eaten.put(me, evening, scrambledEggs, 1);
Do you know of an existing class that has this kind of API? I'm too lazy of writing it myself. ;)
If you look for a more generic approach, and you might have more than 2 or 3 'chain steps', I would suggest in applying some different structural approach, rather than sticking to using only basic collection classes. I have feeling that Composite Pattern could be the right choice if it's correctly applied.
EDIT: due to example requested
The full example would be somewhat time consuming, so let me just explain my idea with dirty Java/pseudocode mix (I'm not even sure if I've missed something!!!). Let's consider we have class BaseMap:
abstract class BaseMap {
public abstract Object getValue(Object.. keys);
public abstract void putValue(Object value, Object.. keys);
}
Then we could have ObjectMap that would be the 'leaf' of our composite structure:
class ObjectsMap extends BaseMap {
private Map<Object, Object> map = new [...]
public Object getValue(Object.. keys) {
// assert that keys.length == 1
return map.get(keys[0]);
}
public void putValue(Object value, Object.. keys) {
// assert that keys.length = 1
map.put(keys[0], value);
}
}
And the actual composite would be as such:
class CompositeMap extends BaseMap {
private Map<Object, BaseMap> compositeMaps = new [...]
public Object getValue(Object.. keys) {
// assert that keys.length > 1
return compositeMap.get(keys[0]).getValue(/* System.arrayCopy => subset of elements {keys_1, .. ,keys_max} */);
}
public void putValue(Object value, Object.. keys) {
// assert keys.length > 1
BaseMap newMap = null;
if (keys.length = 2) -> newMap = new ObjectsMap()
else newMap = new CompositeMap();
newMap.putValue(value, /*subset of keys {keys_1, .. , keys_max}*/);
}
}
You can use org.apache.commons.collections.keyvalue.MultiKey for that: Map<Multikey, Object>
It would be hard to implement a general chained map.
How would the declaration of the class look like? (You can't have a variable number of type parameters.
class ChainedMap<K1..., V>
Another option would be to have a ChainedMapUtil class that performs put / get recursively.
Here is an example of a recursive get. (Quite ugly solution though I must say.)
import java.util.*;
public class Test {
public static Object chainedGet(Map<?, ?> map, Object... keys) {
Object k = keys[0];
if (!map.containsKey(k)) return null;
if (keys.length == 1) return map.get(k);
Object[] tailKeys = Arrays.copyOfRange(keys, 1, keys.length);
return chainedGet((Map<?,?>) map.get(k), tailKeys);
}
public static void main(String[] arg) {
Map<String, String> m1 = new HashMap<String, String>();
m1.put("ipsum", "dolor");
Map<Integer, Map<String, String>> m2 =
new HashMap<Integer, Map<String, String>>();
m2.put(17, m1);
Map<String, Map<Integer, Map<String, String>>> chained =
new HashMap<String, Map<Integer, Map<String, String>>>();
chained.put("lorem", m2);
System.out.println(chainedGet(chained, "lorem", 17, "ipsum")); // dolor
System.out.println(chainedGet(chained, "lorem", 19, "ipsum")); // null
}
}
If you are going to write your own, I would suggest
eaten.increment(me, evening, scrambledEggs);
You could use a composite key
eaten.increment(Key.of(me, evening, scrambledEggs));
(TObjectIntHashMap supports increment and adjust)
You may not even need a custom key.
eaten.increment(me + "," + evening + "," + scrambledEggs);
It is fairly easy to decompose the key with split()
I once made a map using 3 keys just for fun.May be you can use it instead of using chained maps:
public class ThreeKeyMap<K1,K2,K3,V>{
class wrap{
K1 k1;
K2 k2;
K3 k3;
public wrap(K1 k1,K2 k2,K3 k3) {
this.k1=k1;this.k2=k2;this.k3=k3;
}
#Override
public boolean equals(Object arg0) {
// TODO Auto-generated method stub
wrap o=(wrap)arg0;
if(!this.k1.equals(o.k1))
return false;
if(!this.k2.equals(o.k2))
return false;
if(!this.k2.equals(o.k2))
return false;
return true;
}
#Override
public int hashCode() {
int result=17;
result=37*result+k1.hashCode();
result=37*result+k2.hashCode();
result=37*result+k3.hashCode();
return result;
}
}
HashMap<wrap,V> map=new HashMap<wrap, V>();
public V put(K1 k1,K2 k2,K3 k3,V arg1) {
return map.put(new wrap(k1,k2,k3), arg1);
}
public V get(Object k1,Object k2,Object k3) {
return map.get(new wrap((K1)k1,(K2)k2,(K3)k3));
}
public static void main(String[] args) {
ThreeKeyMap<Integer,Integer,Integer,String> birthDay=new ThreeKeyMap<Integer, Integer, Integer, String>();
birthDay.put(1, 1,1986,"Emil");
birthDay.put(2,4,2009, "Ansih");
birthDay.put(1, 1,1986,"Praveen");
System.out.println(birthDay.get(1,1,1986));
}
}
UPDATE:
As #Arturs Licis suggested.I looked up in net for composite pattern and I wrote a sample using it.I guess this is composite..Please comment if it is not so.
Person class:
public class Person {
private final String name;
private Map<Time, Food> map = new HashMap<Time, Food>();
public Person(String name) {
this.name = name;
}
void addTimeFood(Time time, Food food) {
map.put(time, food);
}
public String getName() {
return name;
}
Food getFood(Time time) {
Food tmp = null;
return (tmp = map.get(time)) == null ? Food.NoFood : tmp;
}
// main to test the person class
public static void main(String[] args) {
Person p1 = new Person("Jack");
p1.addTimeFood(Time.morning, Food.Bread);
p1.addTimeFood(Time.evening, Food.Chicken);
Person p2 = new Person("Jill");
p2.addTimeFood(Time.morning, Food.Egg);
p2.addTimeFood(Time.evening, Food.Rice);
Map<String, Person> map = new HashMap<String, Person>();
map.put(p1.getName(), p1);
map.put(p2.getName(), p2);
System.out.println(map.get("Jack").getFood(Time.evening));
}
#Override
public String toString() {
StringBuilder b = new StringBuilder();
b.append(name).append("\n");
b.append(map);
return b.toString();
}
}
Food class:
public enum Food {
Rice,
Egg,
Chicken,
Bread,
NoFood;
}
Time class:
public enum Time {
morning,
evening,
night
}