Java: Getting object associated with enum - java

I have an ArrayList full of custom objects. I need to save this ArrayList to a Bundle and then retrieve it later.
Having failed with both Serializable and Parcelable, I'm now simply trying to somehow save the objects that are associated with the indexes in the ArrayList, then checking these when restoring the Bundle and adding the objects back in.
What I have is something like this:
When saving the Bundle:
//Create temporary array of the same length as my ArrayList
String [] tempStringArray = new String[myList.size()];
//Convert the enum to a string and save it in the temporary array
for (int i = 0; i<myList.size();i++){
tempStringArray [i] = myList.get(i).getType(); //returns the enum in string form
}
//Write this to the Bundle
bundle.putStringArray("List", tempStringArray);
So I now have an array of strings representing the enum types of the objects that were originally in the ArrayList.
So, when restoring the Bundle, what I'm trying is something like this:
//Temporary string array
String[] tempStringArray = savedState.getStringArray("List");
//Temporary enum array
ObjectType[] tempEnumArray = new ObjectType[tempStringArray.length];
for (int i = 0; i<tempStringArray.length;i++){
tempEnumArray[i]=ObjectType.valueOf(tempEnemies[i]);
}
So, now I have the enum type of each item that was originally in the ArrayList.
What I'm now trying to do now, is something like (would go inside the for loop above):
myList.add(tempEnumArray[i].ObjectTypeThisEnumRefersTo());
Obviously the "ObjectTypeThisEnumRefersTo()" method above doesn't exist but this is ultimately, what I'm trying to find out. Is this possible or perhaps there is some other way of doing this?

To get an enum value of the enum type Enemy from a string, use
Enemy.valueOf(String).
Enemy.valueOf("SPIDER") would return Enemy.SPIDER, provided your enum looks like
enum Enemy { SPIDER, BEE};
EDIT: It turns out Zippy also had a fixed set of Enemy objects, each mapped to each value of EnemyType, and needed a way to find an Enemy from a given EnemyType. My suggestion is to create a
HashMap<EnemyType, Enemy>
and put all the objects in there upon creation, then at deserialization convert strings to enum values and enum values to Enemy objects using the hashmap.
It later occurred to me though that depending on how much logic you have in Enemy, you might want to consider scrapping either Enemy or EnemyType and combine them into one parameterized enum, similar to the example with Planet over here:http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
That would spare you from having to go two steps from a string to your final object and simplify things a bit as you wouldn't need any hashmap after all.

Related

decoupling object construction tied to input data

What I'm doing
I'm using Dependency Injection to decouple my classes.
How I'm trying to do it
The class I am making constructs ObjectImplementation (the interface) Objects to hold data and it acts as a sort of container. I'm doing this to parse data and cross reference two data-sets. My problem is that I currently have object construction tied to the data being formatted a certain way. I am using the Factory pattern and a properties file "config.properties".
What I want to be able to do
I want to be able to have the factory take in an array of fields or some other similar type and be able to construct instances of the reflected object type without dependencies on the data. In this case they are Salesrep instances but other times I want to construct Salesrep instances or other classtype instances with different fields filled and different ones null without formatting the data to contain the names of fields.
The end goal
The point is so that I can construct different objects with the same container code. If I want to contain the objects differently I'll simply make a new implementation of the parent interface of this container class.
What I'm thinking is the problem
I've figured out that a Fieldmap was a good idea through previous versions of this question and my own research. Yet there is no way to actually set those fields without having something in the data to match to the Fieldmap
Extra Clarification
I really want to know if I can find a way to achieve my goal without adding field names to the data
//creates new properties object and loads in the file configuration
Properties prop = new Properties();
prop.load(SalesRepbyId.class.getResourceAsStream("config.properties"));
//reflects in the class we wish to use
Class<? extends ObjectImplementation> Classtouse = Class.forName(prop.getProperty("ObjectImplementation")).asSubclass(ObjectImplementation.class);
//initializes the data and some hashmaps to store the data or the methods of the reflected class
ArrayList<String[]> Salesrep_contactlist = FileParser.ReadFile();
Map<String, ObjectImplementation> SalesrepByIdMap = new HashMap<>();
Map<String, Method> MethodMap = new HashMap<>();
//adds in the data (fields) by constructing objects of the reflected type using the ObjectImplementation interface
for (String[] fieldarray : Salesrep_contactlist) {
ObjectImplementation object_to_add = null;
try {
//utilizes the factory pattern to return an instance of the reflected class
object_to_add = Factory.getObjectImpl(prop.getProperty("ObjectImplementation"),fieldarray);
/**
uses a method hashmap to map the name of the method to the Method object.
I did it this way because dynamic variable declarations are not possible and
I wanted to decouple Method declarations from the specific class that has
them. If i just hardcoded in which methods I get from the implementing class
that introduces extra dependencies I don't want.
**/
for (Method method:Classtouse.getMethods()) {
MethodMap.put(method.getName(),method);
}
//same as above but for fields this time
for (Field field:Classtouse.getFields()) {
FieldMap.put(field.getName(),field);
}
//object_to_add is a String[] with the format [Fieldname1:fieldinput1,Fieldname2:Fieldinput2]
//so I want to get this array and get each element, seperate the fieldname and then use that string to access the actual Field object of the same name in FieldMap
String fieldname = object_to_add.get(0).split(":").get(0)
String fieldinput = object_to_add.get(0).split(":").get(1)
Field name_example = Fieldmap.get(fieldname)
name_example.set(String.class,fieldinput)
//This requires the data to have the fieldname in it rather than just the fieldinput (or data). Also it confines the input to be strings because I don't think I can use a generic type to set this field even though potentially I would want to.
There is no way for me to dynamically set Field types without something to go off of in the data or elsewhere. In order to avoid something hard coded like: Salesrep rep = new rep (arg1,arg2,arg3 ...) I needed to use the Fieldmap and be able to match the data coming in to what fields I wanted to set. Since I didn't want to do it by order ex:
List list = new list("bob","800-352-4324","foo#example.com");
int i = 0;
for(i = 0, i > list.size(), i++){
Field field = new Field(//need a name here automatically rather than hardcoded)
field.set(object_to_add,list[i])
i++
}
The above didn't have any reference to the actual name of the Field that I actually use in my class. I didn't want that and then it dawned on me that the first line of my data (which is in CSV format) has the Field names effectively listed. ex:
(in the CSV File) foo.txt:
1: name,phonenumber,email
2: "bob","800-352-4324","foo#example.com"
3: "steve","800-444-4444","annoyingcommercials#example.com"
4: ...
Using this knowledge My solution is to use the first line of my data to specify the field names and their order so that when I take in lines as an array of these strings I can use the first line array as a reference to how to set the fields. I will know that the first element in the array should be the name the second should be the number ect ect. This way I only have to change the first line if I want to change how many fields the data holding class actually has.
puesdocode:
ObjectImpl. Classtouse = refelct in the class to use here from properties file
List(String[]) fieldarray = the raw data taken in and converted to a list of string arrays
String[] firstline = fieldarray.getfirstline()
List(String[]) restoflines = fieldarray.getallotherlines()
for i = 0, i > firstline.size(), i++{
Fieldmap.put(Name of the field from firstline[i], create a new Field object here with the Name);
Field fieldtoset = Fieldmap.get(Name of the field again)
fieldtoset.set(make an instance of the Classtouse here, restoflines[i] which represents the data in the 'Name' column)
}
For some silly reason I had it in my head that there was a way to do this without any change to the data, as if the Factory which created the object could take in arbitrary/generic arguments and somehow just know where each field went. I realized that that was silly because I needed to tell the code how to actually set the fields but In a way that it wasn't hard-coded into the class. This solution puts the dependency on the data so now its not hard-coded into the class. I should have seen this sooner.

Finding size of a ArrayList where list name is passed as a String

I have an ArrayList of a java object with name say, "mylist".
I am getting the name of the list(mylist) from database which comes as a String. I need to find the size of this list in JAVA and need to iterate over it.
Is there a way to do this?
Edit:
To be more clear here, I have a class "Candidate"
class Candidate {
String firstName;
String lastName;
List<Education>educationRecords;
.....
}
class Education {
String school;
String degree;
.....
}
I need to populate Candidate object from a JSONObject whose structure is very different from Candidate object(so can't use Gson or jackson).
The simple fields like firstName, lastName, school and degree are stored in the database.
I fetch a Listfields and iterate over them to set the Candidate object. For setting firstName, lastName, I am using SpEL.
But, for fields like school and degree, it becomes complex as I would need to know the size of education records in JSONObject.
So, what I thought was while iterating over all fields if school field is present in Education class(using reflection), I would need to check if educationRecords is a of List type in Candidate class and then by some logic X(taking educationRecords as variable name) iterate over it.
It is the logic "X" I am missing.
I don't quite understand the use case here. However, my understanding is that you have an ArrayList<Object> mylist and you need to find the size of it based on a string retrieved from DB.
You can store the list in a cache, where the key is the name of the list and value is the actual object. You can use redis, eh-cache or memcache (Or anything similar) to achieve the same.
So when you retrieve the name from DB, get the corresponding object from the cache and do size() on the object after type casting it. If your are storing the list type instead of object type in the cache, then the last part is not needed (typecasting).
You can use a map:
Map<String, List> listMap = new Hashmap<>();
Each time you create a list - add it to your map with a key that is a name of your list. Once you get a name you can easily check if such list exists in your map, get it, check its size and iterate through it... Be careful that once you are done with your list you should remove it from your map as well as otherwise you will keep them around and it will eat your memory up.

Java multiple type data structure

Is there a data structure in Java which can store different types in it? I mean like storing in an array different types (which actually does not work).
try
List<Object> list = new ArrayList<Object>();
more info in http://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html
You could use an object array but that creates problems when the time comes to retrieve the objects you have stored. However, if you want to get data out of the array, you can only get it as an Object. The following won't work:
int i1 = objects[1]; // Won't work. Integer i2 = objects[2]; // Also won't work.
You have to get it back as an Object:
Object o = objects[0]; // Will work.
You can't get back the original form now.

How to store multiple fields of different datatypes in any 2D array in java?

I want to store three values in a 2D type in java. I know that we can use List and ArrayList for storing 1D values but I need to store more than one field in a specific record. For example i have to enter the details for multiple columns i.e. (1,1),(1,2),(1,3) for details such aaaa, bbbb, cccc for a person and store them in one single row(which may consist of values which are other than string type). It should run in a loop and once details of a person is stored, it should store (2,1),(2,2),(2,3) i.e. again for a new person. How to do that?
And later on, how to retrieve and send the complete set to database together? Please help..
What you might want to do is to create a class that holds all of the information you want to keep related to a single record if it represents a concrete thing and use the List and ArrayList to store those.
What I mean by concrete thing is something that has a finite set of information that will stay the same over each object.
Something like:
public class Person
{
String name;
Integer age;
// etc...
}
This gives you two advantages over using something like a 2D array. First, it will make reading your code easier, since instead of having to remember that arrayName[x][0] is whatever you decide the first field is, you can access it using something like listItem.attributeName. The second advantage is that you can abstract out any common datahandling tasks as class methods instead of having to bloat your main class with it.

Array of Strings to an Array of Objects

Maybe there is a method that does this that I don't know about - I doubt it though - but I'm trying to convert an array of strings to an array of Objects. Here is the problem: I'm reading a file in from the command line. The file represents several classes of the following types each with their own data fields. Vehicle is the parent class of all who follow: Vehicle,Car,American Car, Foreign car, Truck, Bicycle.
I have no problem reading the file into a string array. However I need to create objects of all these types and store them in an array of type Vehicle[]. For example a portion of the file looks like this:
Vehicle
Kim Stanley Robinson
2344 court drive
(221)885-7777
stackoverflow#overflow.com
American Car
John Bunyon
1010 binary lane
(221)885-55643
bgt.com
convertable
made in detroit
union plant
Where Class type is the first line followed by, Owner's Name, address, phone number, email address...Each type has fields particular to it. So a foreign car is not made in Detroit. Each of these fields appear on a separate line in the file. So what I've done is read the entire file into a string array. However, I need to find my types in the array of strings,create objects of those types, and store them in a Vehicle array. My main problem is that each data field is on a separate line. How should I approach this problem?
This is java code by the way.
Initially reading the data into a String array is fine. Then you need to loop through that array, and based on the "first line" of each loop ("Vehicle", "American car" etc) you will know how many subsequent elements of the array belong to the same.
Something like this (i'll let you fill in the blanks yourself):
int i = 0;
ArrayList<vehicle> vehicles = new ArrayList();
while (i < data.length)
{
if (data[i].equalsIgnoreCase("vehicle"))
{
Vehicle vehicle = new Vehicle();
vehicle.setOwner(data[++i]);
...
vehicles.add(vehicle);
}
else if (data[i].equalsIgnoreCase("american car"))
{
...
}
i++;
}
question is unclear. Do you want to know how to parse the file and use the words on each line to create a object of it?
pseudo:
Vehicle_ptr myVeh = null;
for each line in file
switch line
{
case vehicle: myVeh = new Vehicle();
case American Car : myVeh = new AmericanCar();
default:
if (line.startswithaninteger && (myVeh != NULL)) myVeh.address = line;
etcetc.
}
Tips: use typeidentifiers in the textfile.for example:
car:americancar
address:12345 bla
etcetc
Or use a serializer
You could read the file as you are doing just now but when you read a string that is a Class type create an instance of the correct Vehicle type. It would appear that you would then know that the next x lines of the file are properties of that particular type so you would read the properties and set them on your Vehicle instance. You then have your Vehicle instance to add to the Vehicle array.
I would use a Factory pattern that creates Adapters. The factory would take the string (Vehicle, American Car) and the adapter would take the string array and current index. The adapter would be responsible to knowing how many indices to read and return the concrete object (or an interface).
IAdapter adapter = AdapterFactory.Create( "American Car" );
Object concreteObject = adapter.Popluate( stringArray, currentIndex );
Now, if you have control over how the data is stored, you might want to look into standard serialization, even JSON, to make processing easier.
It seems to me you need a factory pattern to build your set of vehicle types from the inputs. The factory can look after determining where one car specification starts and another one ends. It'll then determine the set of fields for a car, and determine the car type. It can then call the appropriate constructor, passing in all the related fields.
This means that a constructor of (say) an American car specifies all the fields that it's interested in. A European car constructor would do the same. Each constructor can assert on what it's been given so you don't create any cars incorrectly.
The factory will look after parsing and separating the inputs, and determining what is to be built. Each type of car's constructor looks after info for that car only, and performs the appropriate asserts.
The factory will maintain the list of cars created, and return that list (of America/European/Japanese) upon completion.
In pseudo-code:
whilst(!done) {
fields.add(fieldFromFile);
if (carSpecificationCompleted) {
type = getType(fields);
if (type == 'American') {
car = new AmericanCar(fields);
}
else if (type == 'European') {
car = new EuropeanCar(fields);
}
cars.add(car);
clearStoredFields();
}
}
Do you have control of the file being passed in? If so, might I suggest formatting it using XML and then parsing it using JDOM? It would make your life easier in terms of parsing. For example, you could format all vehicle entries like this:
<node type="vehicle>
<attributes location="detroit" color="red" />
</node>
Or whatever format you come up with. The benefit of this is you can then read in only the vehicles (or whatever you want), or use XPath or some other technology to efficiently get the info you want/need and load it to the proper datatype.
Disregard this advice if you have no control over file formatting.
When you have the choice, change your file format.
You can serialize your object by using xstream. Then you only have to store the complete Java object without checking if some value is existing.
I'd use the Builder pattern here instead of Factory. No big difference but find it a bit easier when the parameters vary like it seems to do in his example.

Categories

Resources