So i recently went from Javascript to Java codebase for an automation framework, when it comes to data supplied to our page object methods we usually used an object in javascript shown as this:
const subscriptionInfo = { name : "sub1", cost : 3, active : true, }
I want create the same effect in Java and my solution was creating a DataObject class that used HashMaps for the various different value Types a “DataObject” could hold. Example:
public class DataObject() { public Map<String, String> stringValues; public Map<String, Integer> integerValues; public Map<String, Boolean> booleanValues; // insert more Map<String, whateverType> varname; public DataObject() { stringValues = new HashMap<String, String>(); integerValues = new HashMap<String, Integer>(); booleanValues = new HashMap<String, boolean>(); // instantiate all maps in the constructor } public addStringValues(String keyName, String s) { stringValues.put(keyName, s); } public getStringValues(String keyName) { if(stringValues.containsKey(keyName) { return stringValues.get(keyName); } } // same type of methods for the other data types }
My problem with this approach is that sometimes my “DataObject” maybe only need to hold Strings, or Strings and Integers. With the approach i made, i am taking up unused resources to instantiate other types that wont be added to the DataObject. So i thought the better approach would be the following:
private Map<String, Map<String, Object>> objectMap; public DataObject() { objectMap = new HashMap<String, Map<String, Object>>(); } public void addStringValue(String keyName, String s) { if(!objectMap.containsKey("stringValues")) { Map<String, String> stringValues = new HashMap<String, String>(); objectMap.put("stringValues", stringValues); } objectMap.get("stringValues").put(keyName, s); }
This way i can have methods that will ensure type safety and use HashMaps within this objectMap to store the data according to the correct type, and this allows for the HashMaps to be dynamically generated when the DataObject add methods are called, and the DataObject in the automation scripts will hold only the types it needs to store. The problem I’m encountering is that the objectMap cannot support the stringValues map because stringValues is of type: <String, String>.
Anyway i can get the objectMap to store the stringValues Map?
Advertisement
Answer
Instead of using Hashmap, use java generic types:
here is a snippet for this scenario:
class DataObject { List<DataTypeContainer> dataList; public List<DataTypeContainer> getDataList() { return dataList; } public void setDataList(List<DataTypeContainer> dataList) { this.dataList = dataList; } @Override public String toString() { return "DataObject{" + "dataList=" + dataList + '}'; } } class DataTypeContainer<T> { private String key; private T value; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public T getValue() { return value; } public void setValue(T value) { this.value = value; } public DataTypeContainer(String key, T value) { this.key = key; this.value = value; } @Override public String toString() { return "DataTypeContainer{" + "key='" + key + ''' + ", value=" + value + '}'; } }
Main class
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { DataObject dataObject = new DataObject(); dataObject.setDataList(Arrays.asList( new DataTypeContainer<>("name", "sub1"), new DataTypeContainer<>("cost", 3), new DataTypeContainer<>("active", true)) ); System.out.println(dataObject); } }
Output :
DataObject{dataList=[GenericClass{key=’name’, value=sub1}, DataTypeContainer{key=’cost’, value=3}, GenericClass{key=’active’, value=true}]}