In my current project, I want to convert List<String> to RegionLabel Object.
For instance, User enters String value one by one in order -- center, floor, room . I am storing user's input into List.
Now, my internal data structure in RegionLabel( String centerString, String floorString, String roomString);
My requirement is to convert List<String> data structure into RegionLabel("center", floor", "room" ); data structure.
One note:
My RegionLabel class is generated on-fly. On-fly means at design time, I do not know that "how many arguments RegionLabel constructors have?"
-Pankesh
Perhaps you're just after
new RegionLabel(list.get(0), list.get(1), list.get(2))
I do not know that "how many arguments RegionLabel constructors have?"
Then you'll have to use reflection, or provide a constructor that accepts a List<String> as argument.
Create a new constructor like RegionLabel(List<String> list). This should do.
public RegionLabel(List<String> list) throws Exception{
if( null == list || list.size() < 3 )
throw new Exception("illegal parameter");
this.centre = list.get(0);
...
}
RegionLabel label = new RegionLabel(inputList.get(0), inputList.get(1), inputList.get(2));
Simplified without any errorhandling or validation but without any more constraints on your "conversion", it's hard to be more generic.
Related
I have an object which contains some package-private member variables and I'm adding them to a Google Sheets v4 ValueRange in another object. The current code looks a little bit like this:
List<List<Object>> data = new ArrayList<>();
...
/**
* Sets all the values in the ValueRange member variable
* #return the ValueRange object
*/
ValueRange requestBuilder() {
...
//For each case, add it to the value range
for (int i = 0; i < closedCases.size(); i++) {
data.add(
Arrays.asList(
closedCases.get(i).number,
closedCases.get(i).priority,
closedCases.get(i).firstResp,
closedCases.get(i).accName,
closedCases.get(i).subject,
closedCases.get(i).assigned,
closedCases.get(i).lastUpdated,
closedCases.get(i).daysOld,
closedCases.get(i).jiraCase
)
);
}
vr.setValues(data);
return vr;
}
The question that I'm seeking to answer is, is there any way to do Arrays.asList( closeCases.get(i) ) or add some kind of method on the case object to simply fill all that stuff in, rather than calling out each member variable in the Arrays.asList(). I'm also aware I can use a foreach, but would still need to use the same notation for adding items, which is what I'm trying to avoid.
In case anyone is interested, closedCases is just an ArrayList of an object with some strings and doubles in it.
You somehow need to specify what fields go into this list, in what order. If you want to capture all fields, you could use reflection to iterate over the object (potentially choosing declared, not inherited fields, and potentially choosing only package-private fields), as described here.
But that is not the idiomatic way to do it in Java.
Can you change the definition of the "object which contains some package-private member variables" so that instead it has a Map with key-value pairs?
You could add a List field in the object that is held by closedcases and call that field from inside the loop.
For instance, say the object is Foo,
Inside foo, create a field:
ArrayList<String> allFields = new ArrayList<String>{number. priority …… };
Method:
public ArrayList<String> getAll() {
return allFields;
}
And from inside the loop, just do
data.add(closedCases.get(i).getAll());
If the fields are not just string, you could create different arraylist that holds different types of object, which will increase the list again but could be substantially less that what you gave us.
i have written the following method in JAVA:
protected List<Symbol> fields = new ArrayList<OCLFieldSymbol>(); (**)
public List<Symbol> getArgs(TypeArt kind) {
return (kind, fields);
}
I use Eclipse and it underlines "fields" in the return section with red. When I put the mouse to the red-underlined place, Exclipse makes the following suggestions:
Create field `fields` in type `TypeArt`
Create constant fields in type `TypeArt`
But I do not want to create such a field. It should return the "fields" from the first line (see (**)).
What can I do ? I am new in JAVA and learning it. So I hope someone can help me.
best regards
Java methods are limited to at most one return value, in this case a List<Symbol>. If you really need to have multiple values returned--and you usually don't--you will need to make a class to contain them.
In this case, you're already passing kind in as a parameter, so it doesn't make sense to try to return it; just return fields.
you could try something like this:
public List<Symbol> getArgs(TypeArt kind) {
List<Symbol> temp= new ArrayList<Symbol>();
for (Symbol field:fields){
//determine if field is the kind you want it to be
//if it is add it to temp using temp.add(field)
}
return temp;
}
If you want to return all the elements from fields that are of type kind you first need to create a new list using new List<Symbol>. Once the list is set up you then need to go though the list and determine which ones are the type you want. If they match the type you want you add them to your new list. when you are done looping you return the new list. In your method you told it that it will be returning a List<Symbol> that means that the return statement needs to be a list of symbols. (kind, fields) is not a List object.
Original code from here.
Looking at the code below (ignoring import statements):
public class JsonTest2 {
public static void main(String[] args){
Gson gson = new Gson();
JsonParser jsonParser = new JsonParser();
JsonReader reader = null;
try {
reader = new JsonReader(new InputStreamReader(new
FileInputStream("./twitterUser.json")));
}
catch (IOException e) {
}
JsonArray userArray = jsonParser.parse(reader).getAsJsonArray();
List<TwitterUser> twitterUsers = new ArrayList<TwitterUser>();
//For each element in the JSON array, create a new TwitterUser
//and populate with the json data:
for ( JsonElement aUser : userArray ) {
TwitterUser aTwitterUser =
gson.fromJson(aUser, TwitterUser.class);
twitterUsers.add(aTwitterUser);
}
//For each new TwitterUser that was created, print them out:
for ( TwitterUser tUser : twitterUsers) {
System.out.println(tUser);
}
}
}
The array List twitterUsers = new ArrayList(); gets created and contains two instances of TwitterUser.
How do I reference each instance individually (what is their variable name)? If this is not possible e.g. you can only use TwitterUser[0], how can I use JSON to create say five objects each with individual variable names?
Also a bit of explaining-around the subject is probably needed...
A List is not an array. An ArrayList is a List that is backed by an array (that you can't access directly). Instead you use the List interface to
List.get(int) which Returns the element at the specified position in this list.
Use the List.iterator() to iterate the List, perhaps indirectly with a for-each loop.
So, for the first case
TwitterUser tu = twitterUsers.get(0); // <-- get the first TwitterUser
// in the List.
or for the second
for (TwitterUser tu : twitterUsers) {
// do something with each TwitterUser in tu
}
How do I reference each instance individually
As twitterUsers[0] and twitterUsers[1].
(what is their variable name)?
They aren't variables, and they don't have names.
If this is not possible e.g. you can only use TwitterUser[0], how can I use JSON to create say five objects each with individual variable names?
You can't. Variable names things that you write in your source code ... before it is compiled. A library class (such as the JSON library you are using) can only do things at runtime ... after the source code is compiled.
But if you really want different variables, then it is easy to write your code to do this, provided you know exactly how many variables are required; e.g.
TwitterUser userOne = twitterUsers[0];
TwitterUser userTwo = twitterUsers[1];
Obviously, this is hard-wiring the assumption that there are (at least) two elements in the JSON array you will be receiving.
Is this a good idea? Probably not:
It doesn't scale.
If the number of variables to be populated is not constant, your code gets rather complicated and fragile. (You can initialize them to null, but you then have to deal with possible nulls each time you use the variables!)
You are hard-wiring assumptions that typically shouldn't be hard-wired. (At a minimum you should check that the number of elements in the JSON array matches your expectations ... and treat an incorrect assumption as an error!)
But in some circumstances, it could make the code easier to read; e.g. if the named variables (userOne and userTwo) are going to be used extensively, or they have more descriptive names.
What about using a Map instead of variables? It does scale (sort of) but you still have problems when the number of entries in the array is variable. And the code is more complicated.
Scenario:
I have a hierarchy of subclasses all inheriting from a single distance ancestral class. All super classes in the hierarchy are abstract, so the only concrete classes are those without subclasses. I have an array:
AncestralClass[] someObjects1 = new AncestralClass[someLength];
The ancestralClass is the single super class at the top of the hierarchy that all other classes inherit from.
This array is populated with different objects of the various concrete subclasses. For example:
someObjects1[4] = new SubclassObject();
... and so on.
I have a second array of the same exact form (same type, size, etc), but the second array uses the first array to populate itself with objects again belonging to the various concrete subclasses. To be more specific, the object type in an element in the second array, will be decided based on the object type found in the same element of the first array. So the problem I have is this: I won't know what is contained in the first array because its contents are generated randomly at runtime, therefore I will not know what the contents of the second array should be as they are dependent on the first array. I am not sure how to write the code that instantiates the new objects in the second array. Written in English, what I want to happen sounds so simple and easy. I want to loop through the second array, check the corresponding position in the first array, check what kind of object that is, and then instantiate a new object of that type in the second array. That right there is what I don't know how to code:
someObjects2[i] = new (subclass that someObjects1[i] belongs to)();
Question
To be more general, I want to instantiate a new object that is a new instance of a class an existing object belongs to. How do I do this, and I'm sure there's multiple solutions, so which is better?
It seems from your description that you know beforehand the set of possible concrete classes in the first array. You can do something like:
for (int i = 0; i < array1.length; i++) {
if (array1[i] instanceof SubclassObject1) {
array2[i] = new SubclassObject1();
} else if (array1[i] instanceof SubclassObject2) {
array2[i] = new SubclassObject2();
}
....
}
I think this idea is sort of dubious. There's all sorts of problems you can run into trying to create classes of types you don't control in advance.
So if I did this, the first thing I would do is to use a simple factory method, which is the most basic creational pattern. This way you have all your code isolated in one spot, so if you need to change it later, you can. Then I would just use reflection to create the object.
public class Creation
{
private Creation() {}
public static <S, T extends S> S makeNew( T obj )
throws InstantiationException, IllegalAccessException
{
return (S) ( obj.getClass().newInstance() );
}
// Demonstration
public static void main( String[] args )
throws InstantiationException, IllegalAccessException
{
CharSequence[] cs = { new StringBuilder(), new Segment() };
for( CharSequence c : cs ) System.out.println( makeNew( c ) );
}
}
This will work for simple cases. If you need to use a fancy library like Objenesis in the future, you have an easy place to make your changes.
here i am trying to add elements to the array.
the elements i am trying to add are text fields, so im basically trying to store persons contact details within the array list?
any help would be greatful
public void addContact()
{
ArrayList<String> details = new ArrayList<String>();
{
details.get(txtname(0));
details.get(txtnum(1));
details.get(txtmob(2));
details.get(txtadd1(3));
}
}
It sounds like you haven't thought out the entire problem yet.
Adding elements to an ArrayList in Java is done like this:
public void addContact(){
ArrayList<String> foo = new ArrayList<String>();
foo.add("HELLO");
foo.add("WORLD");
}
yankee2905 explains it very well; that's what you need to get your code to work with an ArrayList.
As a side note, you're not dealing with an array, you're dealing with an ArrayList. For an array, you might have something like this:
String[] details = new String[4];
details[0] = "First";
details[1] = "Second";
details[2] = "Third";
details[3] = "Last";
It almost sounds like you're trying to use an ArrayList to store contact information for multiple people. If that is the case, you will probably want to do it a bit differently. You can create a Contact object that has members for each piece of information you want to store (e.g. firstname, lastname, phone, mobile, address1, address2, etc). Then you can just add Contact objects to your ArrayList like:
Contact contact1 = new Contact();
contact1.setFirstname("Bob");
myArrayList.add(contact1);
public void addContact()
{
ArrayList<String> details = new ArrayList<String>();
{
details.add(//Insert value from post here);
details.add(//Insert value from post here);
details.add(//Insert value from post here);
details.add(//Insert value from post here);
}
}
I've not used java in a while maybe someone will add to this.
You need set or add, not get. See the docs here.
And to get the text from the textfields, use getText.
So you'd have something like:
myArrayList.add(myTextField.getText());
You are trying to use inbuilt array initializer syntax. That does not work on container classes (unless its some new fangled way in c#) you need to use details.add() (or the appropriate member function).
The syntax you are trying to use is for the language supported hardwired array types. In C++ this would look like char x[6] = {'h','e','l','l','o'};. However a container is not an array its a container object. Container objects often mimic arrays by overloading operator[] however they use different data structures behind the scenes -- i.e., they do not use contiguous regions of memory.
p.s., If this was c#.NET -- which I initially assumed -- there is a new mechanism to map array initialization to container object creation. I'll leave it down there for anyone that is interested.
in C# 3.5 using array initializer syntax you can do the following :
public void addContact()
{
ArrayList<String> details = new ArrayList<String>()
{
details.get(txtname(0)),
details.get(txtnum(1)),
details.get(txtmob(2)),
details.get(txtadd1(3))
}
}
Gotta love Microsoft and C# :P
public void addContact()
{
ArrayList<String> details = new ArrayList<String>();
details.add(txtname.getText());
details.add(txtnum.getText());
details.add(txtmob.getText());
details.add(txtadd1.getText());
}
Sorry I don't have an IDE open, but I think this is closer to what you are after.
I think this is the best solution if you want to create an array with some elements:
String[] images = {"a.png","b.png","c.png"};
or
String[] images;
images = new String[]{"a.png","b.png","c.png"};