java reflection to create field/value hashmap - java

I need to create a Hashmap of field/values contained in an Entity, so I can can use them to replace them in a String containing tags with the field names.
I have this code:
public static String replaceTags(String message, Map<String, String> tags) ...
Which replaces all tags found in message for the equivalent values in tags, but in order to build the Map table I need to take "any" Entity and be able to create a Map from the Entity. So, how could I make that possible? to get a routine where I send the Entity and get as return a Map with all the fields and values.
public static Map<String, String> getMapFromEntity(Object entity){
Map<String, String> map = new HashMap<String, String>();
...?????
return map;
}
I know I could use reflection and this is the only approach I have found to get this done, but is there any other way to accomplish the same?, I mean a more efficient way.
Thanks.

Field[] fields = entity.getClass().getFields();
Map<String, String> map = new HashMap<String, String>();
for(Field f : fields)
map.put(f.getName(),(String) f.get(entity));
O, and your entity should be an object of your class, not your class itself.
If your fields are private and you have getters for them, you should use getMethods() and check if method name starts with "get" prefix.Like this:
Method[] methods = entity.getClass().getMethods();
Map<String, String> map = new HashMap<String, String>();
for(Method m : methods)
{
if(m.getName().startsWith("get"))
{
String value = (String) m.invoke(entity);
map.put(m.getName().substring(3), value);
}
}

If all you want to get out of this is a map, why not use a literary like Jackson, then you can simply convert it like this
Map map = new ObjectMapper().convertValue(object, Map.class);

I know I could use reflection and this is the only approach I have
found to get this done, but is there any other way to accomplish the
same?
As far as I know, reflection is the only way to accomplish this, unless the class(es) you want to build the map from implement some interface, and your code extracting the map is aware of this interface.

Related

How to create a map with enum values in java?

I need to validate the value of a parameters passed as part of REST API. These parameters are a fixed set of values. I thought of using a map having parameter name as key and enum as value. So I can check if the value sent in REST API is one of the enum keys.
But I am not able to create a Map with String key and enum value in java, tried creating Map and then putting and enum as value, but it fails.
class Validation {
enum Type {
INTERNAL,
EXTERNAL
};
}
Map<String, Object> validationMap = new HashMap<String, Object>();
validationMap.put("type", Validation.Type);
This is throwing an error that type is not defined.
This is probably what you're looking for, Map<String, Object> is changed to Map<String, Validation.type>:
Map<String, Validation.type> validationMap = new HashMap<String, Validation.type>();
validationMap.put("type", Validation.type.INTERNAL);
validationMap.put("type2", Validation.type.EXTERNAL);
Your original code would have worked, if you had changed Validation.type to Validation.type.INTERNAL for example, however your validationMap map allows the storage of any Object, so validationMap.put("type2", 123.123); would also have worked, which is unlikely to be something you want.
Is this what you need?
Map<String, List<Validation.type>> validationMap = new HashMap<>();
validationMap.put("type",
Arrays.asList(Validation.type.EXTERNAL,Validation.type.INTERNAL));
I believe Your code does not work because Validation.Type is not an instance (of an enum). When you put a value in your map, I believe you would want to put in an actual instance as a value. I suppose that is why the above answers suggest adding an actual instance to the Map such as Type.INTERNAL or using a class instance.
This code will run
Map<String, Object> validationMap = new HashMap<String, Object>();
// this works
validationMap.put("type", Validation.Type.EXTERNAL);
// as shown by:
System.out.println(validationMap.toString());
// here is an analogy:
// make an instance of a class
Validation validation = new Validation();
// this works
validationMap.put("classType",validation);
Validation validationGet = (Validation) validationMap.get("classType");
System.out.println(validationMap.toString());
// by analogy this will not work because Validation is not an instance:
// validationMap.put("classType",Validation);
And the output on my machine is:
{type=EXTERNAL}
{type=EXTERNAL, classType=Validation#3feba861}

How to correctly define a multidimensional generalized Collection in Java?

For example, I want to create a map that is a map of a map of a map. So I have declared the map as so. From a resultset I want to create a JSON object.
Map<String, Map<String, Map<String, String>>> data = new LinkedHashMap<String, Map<String, Map<String, String>>>();
I could define as
Map<String, Object> map = new LinkedHashMap<String, Object>();
however I need to put items one at a time so I get the map I want and put it in. Then the same the following iterations so I would have to cast the object to the map which leaves unchecked warnings.
Is there a better way of declaration of this type of Collection?
You can use a Google Guava MultiMap, but really you're better off creating a new Object and referencing the entire collection of data from the single key.
public class MyObjectData {
private String string1;
private Map<String, String> map;
// Getters and setters
}
Then your map becomes Map<String, MyObjectData>

Is it possible to instantiate a Map with a list of keys?

Usually, if I know beforehand all the keys of a map, I instantiate it like this:
List<String> someKeyList = getSomeList();
Map<String, Object> someMap = new HashMap<String, Object>(someKeyList.size());
for (String key : someKeyList) {
someMap.put(key, null);
}
Is there any way to do this directly without needing to iterate through the list? Something to the effect of:
new HashMap<String, Object>(someKeyList)
My first thought was to edit the map's keyset directly, but the operation is not supported. Is there other way I'm overlooking?
You can use Java 8 Streams :
Map<String,Object> someMap =
someKeyList.stream()
.collect(Collectors.toMap(k->k,k->null));
Note that if you want a specific Map implementation, you'll have to use a different toMap method, in which you can specify it.

How to save enum class in a HashMap?

Let us say we have following enums:
public enum AnimalImages {
TIGER,BEAR,WOLF;
}
public enum CarImages {
BMW,VW,AUDI;
}
Now I want to save these enum classes in a HashMap:
Map<String,Enum<?>> enumMap=new HashMap<String,Enum<?>>();
enumMap.put("AnimalImages",???????);
What I should enter instead of the question marks?
To explicitly answer to your question, you have to put the enum value as this:
Map<String,Enum<?>> enumMap=new HashMap<String,Enum<?>>();
enumMap.put("AnimalImages", AnimalImages.TIGER);
However, if you want to put all the value belonging to an enum, then you could leverage values() method and also change your map to Map<String,Enum<?>[]> so you can use this:
Map<String,Enum<?>[]> enumMap=new HashMap<String,Enum<?>[]>(); // Note Enum<?>[] array
enumMap.put("AnimalImages", AnimalImages.values());
enumMap.put("CarImages", CarImages.values());
Another approach, with a shorten signature can be something like this:
Map<String, Object> enumMap = new HashMap<String,Object>();
enumMap.put("AnimalImages", AnimalImages.values());
enumMap.put("CarImages", CarImages.values());
Another way that bali182 pointed in this comment, you could use:
Map<String, Collection<? extends Enum<?>>> enumMap = new HashMap<>();
enumMap.put("AnimalImages", Arrays.asList(AnimalImages.values()));
enumMap.put("CarImages", Arrays.asList(AnimalImages.values()));
To answer your question:
enumMap.put("AnimalImages", AnimalImages.WOLF);
enumMap.put("Cars", CarImages.AUDI);
But you can also do
Map<String, AnimalImages> enumMap = new HashMap<String, AnimalImages>();
And this way enumMap.get("AnimalImages"), and this way you won't have to type check and cast it.
If the requirement is to create a Map that contains all values of a given enum, I would use a mapping of String keys into EnumSet values:
Map<String, EnumSet<?>> enumMap = new HashMap<String, EnumSet<?>>();
enumMap.put("AnimalImages", EnumSet.allOf(AnimalImages.class));
enumMap.put("CarImages", EnumSet.allOf(CarImages.class));
for (Map.Entry<String, EnumSet<?>> e : enumMap.entrySet()) {
System.out.println(String.format("key: [%s], values: %s",
e.getKey(), e.getValue().toString()));
}
EnumSet is a specialized Set implementation, which is represented internally as a bit vector. Its sole purpose is to provide an efficient and easy way to store enums.

Define a map as constant in java

For my Android app I've the need of defining some keys in a single constant, and I think the best way to do it is using a map. But not sure whether that's really the way to go, and how to do it correctly. As I'm targeting Android, a Bundle may also be an option.
I have a list of keys like:
"h" = "http"
"f" = "ftp"
Basically the program is to read a QR code (to keep that code from growing too big I'm using super-short keys), gets those keys, and has to translate them to something useful, in my case a protocol.
I'm trying to define a constant called KEY_PROTOCOLS, I think this should be a Map, so later I can call something like KEY_PROTOCOLS.get("f") to get the protocol that belongs to key "f".
Other classes should also be able to import this constant, and use it. So this map has to be populated in the class right away.
How can I do this?
If the constant is shared by several classes, and if you want to make sure this map is not cleared or modified by some code, you'd better make it unmodifiable :
public static final Map<String, String> KEY_PROTOCOLS;
static {
Map<String, String> map = new HashMap<String, String>();
map.put("f", "ftp");
// ...
KEY_PROTOCOLS = Collections.unmodifiableMap(map);
}
Something like this:
private static final Map<String, String> KEY_PROTOCOLS = new HashMap<String, String>();
static{
KEY_PROTOCOLS.put("f", "ftp");
// More
}
Static Initialisers:
http://www.glenmccl.com/tip_003.htm
This would work.
static Map<String, String> map = new HashMap<String, String>();
static {
map.add("ftp", "ftp");
...
}
On android:
#SuppressWarnings("unchecked")
Pair<String,String>[] pre_ips=new Pair[]{new Pair<String,String>("173.194", "0"), new Pair<String,String>("74.125", "96")};
String ip_1_2,ip_3;
for (Pair<String,String> pre_ip:pre_ips)
{ip_1_2=pre_ip.first;
ip_3=pre_ip.second;
}

Categories

Resources