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;
}
Related
I have the below abstract class where character_1, character_2, character_3 are decleared.
public abstract class Properties {
public static final String character_1 = "//*[#class='character- nav-slide-normal'][#alt='CHARLIE E LOLA']";
public static final String character_2 = "//*[#class='character-nav-slide-normal'][#alt='PEPPA']";
public static final String character_3 = "//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']";
}
How can I parameterise that and passing through to properties.
String[] myStringArray = {"character_1","character_2","character_3"};
for (int i = 0; i < myStringArray.length; i++)
{
String value = myStringArray[i];
String altvalue = driver.findElement(By.xpath(Properties.value)).getAttribute("alt");
System.out.print(altvalue);
}
I'd say the easiest is to use a HashMap<String, String>.
public class Properties { //no particular use to make this class abstract
public static final Map<String, String> characters;
static
{
characters = new HashMap<String, String>();
characters.put("character_1", "//*[#class='character- nav-slide-normal'][#alt='CHARLIE E LOLA']");
characters.put("character_2", "//*[#class='character-nav-slide-normal'][#alt='PEPPA']");
characters.put("character_3", "//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']");
}
}
//somewhere else...
String[] myStringArray = {"character_1","character_2","character_3"};
for (String stringArrayString : myStringArray)
{
String xPath = Properties.characters.get(stringArrayString);
String altvalue = driver.findElement(By.xpath(xPath)).getAttribute("alt");
System.out.print(altvalue);
}
You can easily use above code to solve your problem.
However, your quote indicates that you already have something in mind:
I need how to send the value (i.e myStringArray[i] ) to Properties.
???????? so that when i = 0, String altvalue =
driver.findElement(By.xpath(Properties.character_1)).getAttribute("alt");
when i=1 , String altvalue =
driver.findElement(By.xpath(Properties.character_2)).getAttribute("alt");
like that.
While it is possible with reflection, it is heavily discouraged: you lose compile-time type safety, it causes bugs when refactoring, and performance is slower.
You could use an enum. Something along the lines of
public enum Properties {
CHARACTER_1("//*[#class='character- nav-slide-normal'][#alt='CHARLIE E LOLA']"),
CHARACTER_2("//*[#class='character-nav-slide-normal'][#alt='PEPPA']"),
CHARACTER_3("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_4("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_5("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_6("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_7("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']");
private String xpath;
Properties(String xpath) {
this.xpath = xpath;
}
public String getXpath() {
return xpath;
}
}
Example
// Selective properties
Properties[] selectiveProperties = {Properties.CHARACTER_1, Properties.CHARACTER_3, Properties.CHARACTER_6, Properties.CHARACTER_7};
for (Properties property : selectiveProperties) {
String altvalue = driver.findElement(By.xpath(property.getXpath())).getAttribute("alt");
System.out.print(altvalue);
}
//Iterate through all the properties
for (Properties property : Properties.values()) {
String altvalue = driver.findElement(By.xpath(property.getXpath())).getAttribute("alt");
System.out.print(altvalue);
}
I want to make a Map (String ,Object) like this
{AssessmentId=0, Physical_name='ram', Physical_height=20, Physical_weight=60}
from my Pojo Class - InitialAssessment
public class InitialAssessment {
private long AssessmentId;
private String physical_name;
private String physical_gender;
private int physical_height;
private float physical_weight;
// all getter And setter is Created here
}
without using any external Library like Gson etc.
You can use this approach:
public Map getMapFromPojo(InitialAssessment assessment) throws Exception {
Map<String, Object> map = new HashMap<>();
if (assessment != null) {
Method[] methods = assessment.getClass().getMethods();
for (Method method : methods) {
String name = method.getName();
if (name.startsWith("get") && !name.equalsIgnoreCase("getClass")) {
Object value = "";
try {
value = method.invoke(assessment);
map.put(name.substring(name.indexOf("get") + 3), value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return map;
}
return null;
}
It will give you map for pojo class like this:
Output:
{AssessmentId=0, Physical_name='ram', Physical_gender='Male' , Physical_height=20, Physical_weight=60}
I am struggling to find a way to dispatch this to functions in java8
Person p = registry.getPerson();
if (field == Field.LASTNAME) {
p.setLastName(str);
}
if (field == Field.FIRSTNAME) {
p.setFirstName(str);
}
if (field == Field.MIDDLENAME) {
p.setMiddleName(str);
}
My idea is to use some kind of function dispatch table to replace the if statements in the case of more cases:
Map<Integer, Function> map = new HashMap<Integer, Function>
static {
map.put(1, new Function<String, String>() {
#Override
public Object apply(String str) {
person.setLastName(str);
return str;
}
}
}
But the code cannot compile, because i need to pass the person object some place. Anyone knows a pattern for this?
Assuming Field is an enum, you can add BiConsumer<Person,String> as an enum field:
class Person {
static enum Field {
FIRSTNAME(Person::setFirstName),
MIDDLENAME(Person::setMiddleName),
LASTNAME(Person::setLastName)
;
private BiConsumer<Person, String> setter;
private Field(BiConsumer<Person, String> setter) {
this.setter = setter;
}
}
public void set(Field field, String str) {
field.setter.accept(this, str);
}
......
}
Instead of storing Function<String,String>, you can store BiFunction<Person,String,String> and pass the Person instance in as a parameter.
Map<Integer, BiFunction<Person,String,String>> map =
new HashMap<Integer, BiFunction<Person,String,String>>();
static {
map.put(1, (person, str)->person.setLastName(str));
}
In the interest of simplicity, you could also just store a List of the functions, if you're just going to index them by an integer, it's faster for random access and makes for less complicated generic code:
List<BiFunction<Person,String,String>> list = new ArrayList<BiFunction<Person,String,String>>();
static {
list.add((person, str)->person.setLastName(str));
}
I wanted to create a table/list in Java, and I wonder what is the best way to handle it.
The table should have a structure like this:
Term propertyList entitiesList
a1 p1=1, p2=2, p3=2 T1,T2
a2 p5=0, p4=5 ,p3=3 T2,T1
a3 p1=1 ,p4=3, p3=9 T3,T1,T2
...
a10
I have a list with exactly 10 terms, and for every term there is a list of properties (deep with key and value), and the properties can be either in one or more entities.
I need some help on how to create it, e.g. should I use list, map, collection etc.
How can I add hardcoded values to them as literals in the code, and what is the best way to read data from it, taking into account performance, given that later I will need to use this for every entity and find the related properties that participate in every term.
first off Create Term class.
So you have list of Terms: List<Term>
Term class
public class Term {
private String mName = "";
private Map<String, Integer> mPropertyMap = new LinkedHashMap<String, Integer>();
private List<String> mEntitiesList = new ArrayList<String>();
public Term(String name) {
mName = name;
}
public void generate(Map<String, Integer> propertyMap, List<String> entitiesList) {
mPropertyMap = propertyMap;
mEntitiesList = entitiesList;
}
public Map<String, Integer> getPropertyMap() {
return mPropertyMap;
}
public void setPropertyMap(Map<String, Integer> propertyMap) {
this.mPropertyMap = propertyMap;
}
public List<String> getEntitiesList() {
return mEntitiesList;
}
public void setEntitiesList(List<String> entitiesList) {
this.mEntitiesList = entitiesList;
}
public String getName() {
return mName;
}
public void setmName(String name) {
this.mName = name;
}
}
Main Class
public class MyClass {
private List<Term> mTermList = null;
private void init() {
mTermList = new ArrayList<Term>();
}
private void addSomeTerm() {
Map<String, Integer> propertyMap = new LinkedHashMap<String, Integer>();
propertyMap.put("p1", 1);
propertyMap.put("p2", 2);
propertyMap.put("p3", 3);
List<String> entitiesList = new ArrayList<String>();
entitiesList.add("T1");
entitiesList.add("T2");
Term term = new Term("a1");
term.generate(propertyMap, entitiesList);
mTermList.add(term);
}
private String printTerms() {
StringBuilder buff = new StringBuilder();
for(Term currTerm : mTermList){
buff.append(currTerm.getName()).append(" ");
Map<String, Integer> propertyMap = currTerm.getPropertyMap();
Set<String> sets = propertyMap.keySet();
Iterator<String> itr = sets.iterator();
String key = null;
Integer value = null;
while(itr.hasNext()){
key = itr.next();
value = propertyMap.get(key);
buff.append(key + "=" + value).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
buff.append(" ");
List<String> entitiesList = currTerm.getEntitiesList();
for(String str : entitiesList){
buff.append(str).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
}
return buff.toString();
}
/**
* #param args
*/
public static void main(String[] args) {
MyClass m = new MyClass();
m.init();
m.addSomeTerm();
System.out.println(m.printTerms());
}
}
Output:
a1 p1=1,p2=2,p3=3 T1,T2
It looks like you could have the following structure:
class Term {
String id;
Map<String, String> properties;
List<Entity> entities; // (or Set<Entity> if no duplicates are allowed)
}
But it's not very clear what you mean by "deep" and by "the properties can be either in one or more entities".
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;
}
}