Java Use string as object call - java

Good Afternoon,
i would like to ask regarding the methods to use string as reference.
Let say, that i got two object of type LinkedList named ChinaShip and HongkongShip
Normally, if i wanted to access a method (for example getFirst())
i will type ChinaShip.getFirst()
Now, let say that in other object, i got a variable Destination which content is a String.
The example of the Content will be China and Hongkong
Is it possible to use the content of the variable as the name for accessing the LinkedList object?
my approach first would be concatenate the variable first, which will be Destination + "Ship"
This will produce a string which is ChinaShip and HongkongShip
The reason i'm doing this way rather than comparing the string is that the Destination consist of hundreds of posibilities.
Thank You Very Much.
Regards,

Unfortunately you can't do that in Java. But this is closer with that:
HashMap<String, LinkedList> dest = new HashMap<String, LinkedList>();
dest.put("China", ChinaShip);
dest.put("Hongkong", HongkongShip);
.....
if(dest.containsKey(Destination){
dest.get(Destination).getFirst();
}

You can use the reflection API. If the lists are declared in the class MyClass you can use the following code:
LinkedList list = (LinkedList) MyClass.class.getDeclaredField(Destination + "Ship").get(this);
This assumes that the above code is called from within a MyClass object, otherwise the get(this) call must be changed to get(myClassInstance). Though as MadProgrammer mentions, you might be better of using a Map.

You can use a Map and use the desitnation string as your key because these will be unique:
Map<Desitnation, value> destinations = new HashMap<Desitnation, value>();
then search through the Map for your destination key:
http://www.tutorialspoint.com/java/util/hashmap_get.htm

I think you need to re-work your architecture. You shouldn't have to create method names from Strings.
It seems to me like you need a Ship object which has a destination, and a linkedlist of Ships.
If you need to map ships by destination, what you can also do is have a Map where they key is the destination string, and the value is the linked list of ships going to that destination.
So if you do a map.get("China") you will get a list of ships going to China, and from there you can do what you want.

Related

Is there a data structure in Java that can hold 4 or more values

Is there a data structure in Java which can hold more than 4 values?
So something along the lines of
Map<String, String, String, String>;
This is needed to be able to reduce the number of if else statements I have. I would like to be able to do the following.
check if the data structure contains an element which matches a certain value, if it does then it assigns a link(which is string) to a variable and then adds a code and message to another variable which is related to that link.
if not is there a good workout around to achieve this?
Is there a data structure in Java which can hold more than 4 values?
There are lots of them.
The simplest is probably String[] which can hold 4 strings if you instantiate it like this:
new String[4]
And other Answers give other data structures that might meet your actual (i.e. unstated) requirements.
However, it is probably possible ... let alone sensible ... for us to enumerate all of the possible data structures that can meet your stated requirement.
Hint: you should try to explain how this data structure needs to work.
Hint 2: "the lines of Map<String, String, String, String>" does not help us understand your real requirement because we don't know what you mean by that.
UPDATE - Your explanation is still extremely vague, but I think you need something like this:
Map<String, MyRecord>;
public class MyRecord {
private String link;
private String code;
private String message;
// add constructor, getters, setters as required
}
There is nothing in the standard libraries, but Guava has a nice implementation; called
Multimap
If Guava is not an option in your environment, you will have to re-invent the wheel though.
Use can use MultiMap on Apache,
A MultiMap is a Map with slightly different semantics. Putting a value into the map will add the value to a Collection at that key. Getting a value will return a Collection, holding all the values put to that key
MultiMap mhm = new MultiValueMap();
mhm.put(key, "A");
mhm.put(key, "B");
mhm.put(key, "C");
Collection coll = (Collection) mhm.get(key);
Use Map of map:
Map<String, Map<String, Map<String, String>>>
Reading your question, It seams like you simply need a 'key-value' pair. Key being a 'String', which you have referred as 'a certain value' in your question. Value is a kind of wrapper object wrapping three Strings which you have referred as 'link, code and message'.
I suggest you can simply use
HashMap < String, Wrapper > map;
You can create a class ' Wrapper.java' which can contain three Strings, as instance fields
String link,code,message;
You can instantiate these fields in constructor and later can retrieve them using getter methods or also can have setters to set the values you need. You can provide a better contextual name to the class 'Wrapper.java'.

How to rename or create a new String dynamically?

I have a bunch of strings with weird names (like this docFileeh934fhry) that contain text like this
System.out.println(docFileeh934fhry);
`.............document: 12345.....
...................
...............`
I want to rename these strings. So that the above string will be String doc12345
How can I do this?
I know how to get this number using Pattern.compile
Let's say I have this number String docNumber = "12345";
Now how can I dynamically create a new string?
I tried
String doc+docNumber = docFileeh934fhry; // no result
You might be able to do this with reflection, but it has to be said that this is a very poor approach.
Your naming of variables should not depend on any external input. Instead, give it a name that describes its contents and go from there.
What do you gain by naming it doc1?
If you are looping trough files all you probably want is a currentDocument. Any other variables (firstDocument, nextDocument, oldDocument, etc) you name according to their function, not their contents.
If you want a way to uniquely identify the correct document, create a class instead
class Document {
int id;
string contents;
}
After storing all these Document objects into a collection (like an ArrayList), you can just retrieve the document you need on basis of that id rather than having to mess around with a bunch of generated variables.
Another point to note: how would you even use this when you have 50 documents? 100? 10.000? This would be impossible to maintain.
If you don't want to create a custom class you can go with the HashMap<Integer, String> route.
This isn't how Java works. If you want to associate an object with a String, then use a Map such as a HashMap<String, String>.
Assign the string to the variable w/ the new name. Note that the new name will have to be have been defined when writing the code, it can't be computed on the fly (if that is what you are driving at).
You can't use + in a variable name. As above, you can't make variable names on the fly.
Here maybe one possible solution,use Hashmap,key is your varname(the way as you wish) and value is your string.

is it ok to change the value from outside a Map?

So i have a code snippet here. I go this issue while i was discussing some code with my friend
Map<Integer , List<String>> myMap = new HashMap<Integer , List<String>>();
List<String> list = new ArrayList<String>();
myMap.put(45,list);
List<String> lst = myMap.get(45);
lst.add("String1");
lst.add("String2");
lst.add("String3");
System.out.println(myMap.get(45));
My question here is.
-> If its ok to modify the list outside the map through another reference? I am asking from OOP design point of view.
That is completely ok, IMHO
When you write
List<String> lst = myMap.get(45);
Still it is refering to the value in the map, for the key 45.
Once you get the value(reference to the list), It's up to you what you are doing with it.
If its ok to modify the list outside the map through another reference? I am asking from OOP design point of view.
It really depends on the context in which you're modifying it. If you plan on doing this a lot, with a lot of different values, then you're quickly going to find yourself with very confusing code that is difficult to debug and to follow.
BUT, in your example, you first load it from the map, then you edit it. It's completely clear that the data is coming from your Map object. Provided you make it clear with comments and documentation, especially when you're passing this reference between other methods, this isn't bad practise at all.
It is OK, provided that you take care of any potential synchronizations; e.g. if there are multiple threads that might be modifying the map and / or the list.
You might be confusing this with the case where you modify a key object. That is distinctly NOT ok if the modification breaks the hash table invariants; e.g.
if it causes either the key's hashcode to change, or
if it causes the key to give a different result when compared with some other key used in the table.
I am asking from OOP design point of view.
I'd say that OO design is neutral on this issue. You are using a Java interface (i.e. Map) that doesn't take control of the values. You are not violating encapsulation because the values are not encapsulated by the Map abstraction.
Whether this is sound design from the application perspective depends on the overall design. We can't make a judgement one way or another without understanding the context.
Every reference has a scope, it is your take(based on your requirement) whether you want the Map to be accessed through multiple reference or through a single reference.
It's OK.
After you have added numbers to the list in lines 5-7 in your code snippet, and then you get the list from the map again in line 8, the list you get from the map will have the extra numbers you just added.
That depends on what you want to do with the list and what your requirements are.
I'd say it is ok-ish but it might be better to encapsulate that in another object.
Consider the question what to do with empty lists, should they be removed or kept?
Encapsulation would allow you to ensure that empty lists are removed, since the user would then only access the wrapper, not the list directly.
Btw, with HashMap you have to change the list outside the map ;)
ArrayList is mutable. It is resizeable and keeps the same reference after modification. To have immutable list you should use following code.
List<String> list = Collections.unmodifiableList(new ArrayList<String>());
If you define list above way, than you can't modify it.

What kind of List is List<Object> list = Database.getAllData();?

I have the following question:
if I have the following line of code:
List<Position> allPos = posDBM.getAllPos();
Position is an object
posDBM is a SQLite Database Manager class, which manages the SQLite database,
getAllPos() returns all database data.
The return type of getAllPos() is List<Position>.
If I want to initialize a List<> like this List<Position> pos = new, I have to specify the type of the List (ArrayList, LinkedList, etc.) .
So back to my question, what kind of List do I have, after I filled the list from the database?
I would guess it's an ArrayList , but I can't find any source to back this up. It's just a matter of interest...
You don't have to know; that's the point. The interface is what matters to you, not the implementation.
You can't know without looking at the source of that method. But even if you do, it's immaterial to your client. All you call are List methods.
That you will find in getAllPos() source code. List<Position> due to Polymorphism will accept all classes implementing List interface.
It you are just curious, then one way to find out is to do something like this:
List<Position> allPos = posDBM.getAllPos();
System.out.println("The class is " + allPos.getClass().getName());
Of course, you don't need to know ... because you don't need to instantiate the list implementation class yourself. The database management code deals with that.
The returned List<Position> is a generic or a Strongly Typed list. The option that you were asking is about ArrayList which specifies a list that can take up any object. This will require an overhead of Boxing and Unboxing when writing / reading using the ArrayList.
Ideally you should not worried about the actual implementation , once you have List returned from the method call , you can just iterate over it like this .
List<Position> allPos = posDBM.getAllPos();
for(Position position : allPos){
//Your code goes here
}
And if you want to initialize a new list you can do it in many ways by using different implementations of List interface , now which implementation you want to choose very much depends on your requirement.
I would suggest you to add a breakpoint and see allPos variable after posDBM.getAllPos(), the debugger should tell you the Type.

How to have variables with dynamic data types in Java?

I need to have a UserProfile class that it's just that, a user profile. This user profile has some vital user data of course, but it also needs to have lists of messages sent from the user friends.
I need to save these messages in LinkedList, ArrayList, HashMap and TreeMap. But only one at a time and not duplicate the message for each data structure. Basically, something like a dynamic variable type where I could pick the data type for the messages.
Is this, somehow, possible in Java? Or my best approach is something like this? I mean, have 2 different classes (for the user profile), one where I host the messages as Map<K,V> (and then I use HashMap and TreeMap where appropriately) and another class where I host them as List<E> (and then I use LinkedList and ArrayList where appropriately). And probably use a super class for the UserProfile so I don't have to duplicate variables and methods for fields like data, age, address, etc...
Any thoughts?
First of all, you are not duplicating a message by adding it to different collections at the same time - you only store distinct references to the same object. (Well, unless a message is represented as a primitive type like long... but these can't be added to collections anyway.)
Why can't you have all those collections within the same UserProfile? This would allow you to access messages by key or index, and iterate through them any way you like.
A LinkedHashMap might also be an interesting option for you, as it guarantees iteration order, so in a way it behaves similarly to a List regarding iteration, while still being a Map. Ultimately, it boils down to how you want to access the messages of a given user, which you haven't detailed.
Update: #Snake, you can only store references to objects in Java collections. A primitive long value thus can't be stored directly, only by converting to a Long object first. Note that since Java5, this conversion may be implicit due to autoboxing, so you don't see it in the code, but it still happens nevertheless - e.g.
List<Long> list = new ArrayList<Long>();
list.add(1L); // the primitive value is boxed into a Long object,
// which is then added to the list
long value = list.get(0); // the value of the Long object in the list is outboxed
// and assigned to the primitive variable
If this is a university project, then I suspect that what you are meant to do is this:
Collection mycoll;
mycoll = new ArrayList();
for (Message m:message) {
// do stuff and measure the performance
}
// do other stuff and measure the performance
mycoll = new LinkedList();
// do the same stuff as a above and measure the performance again
mycoll = new HashMap();
//... and so on
As stated above, adding an object to a collection doesn't duplicate it.
I ended up using what I described on the first post:
Is this, somehow, possible in Java? Or
my best approach is something like
this? I mean, have 2 different classes
(for the user profile), one where I
host the messages as Map (and
then I use HashMap and TreeMap where
appropriately) and another class where
I host them as List (and then I use
LinkedList and ArrayList where
appropriately). And probably use a
super class for the UserProfile so I
don't have to duplicate variables and
methods for fields like data, age,
address, etc...

Categories