Adding an Object to Vector loses Reference using Java? - java

I have a Vector that holds a number of objects. My code uses a loop to add objects to the Vector depending on certain conditions. My question is, when I add the object to the Vector, is the original object reference added to the vector or does the Vector make a new instance of the object and adds that?
For example, in the following code:
private Vector numbersToCalculate;
StringBuffer temp = new StringBuffer();
while(currentBuffer.length() > i) {
//Some other code
numbersToCalculate.add(temp);
temp.setLength(0); //resets the temp StringBuffer
}
What I'm doing is adding the "temp" StringBuffer to the numbersToCalculate Vector. Should I be creating a new StringBuffer within the loop and adding that or will this code work? Thanks for the help!
Eric

You need to create a new StringBuffer each time. Each item item in the Vector is just a pointer to the same StringBuffer object, so each time through the loop you are resetting the single instance of stringbuffer and adding the same reference to the Vector.
Just replace the temp.setLength(0); with temp = new StringBuffer();

If you have to have an independent object added to the Vector, create a new one each time.
You're adding references to the vector. If the state of an object changes, then all references to it see the change.

It uses the same object each time. You should add a temp = new StringBuffer(); to the end of your loop. (The result of your loop will be a Vector of pointers to the same single empty StringBuffer.)

The Vector will store the reference you give it, it won't create its own copy of the object. So if you want the Vector to have buffers separate from the one you're continuing to use, as you said you'll need to create those separately by creating a new buffer instead of setting the old one's length to zero.
Off-topic side note: Vector is fairly out of date. you're probably better off with ArrayList (or one of the other classes implementing List, if you don't need an array backing it).

Inserting an element into a collection does not, and can not, make a copy of an object, because Java has no formalized notion of a copy-constructor or operator overloading for user-defined types. That is, a general purpose collection can not know how to copy the contained objects.
Java's assignment operator always copies the pointer, never the contents, of a user-defined type.

As most of the answers here say, a Vector stores references to objects of type Object. If you change the underlying Object each time you will end up with a Vector containing lots of references to one object, which now contains the last value you gave it.
Based on the name of your variables, I'm guessing you actually want to be storing numbers in your Vector.
In an ideal world you would just add object of type int into the Vector. Unfortunately, in Java an int is a 'primitive type', and Vector can only store objects of type Object. This means you can only put Integer objects into the Vector instead of int objects.
So your code will look something like:
// Put a number at index 0
Integer inputNumber = new Integer(7);
numbersToCalculate.add(0, inputNumber);
// Some time later read out the value at index 0
Object objFromVector = numbersToCalculate.elementAt(0);
// Cast the Object to an Integer
Integer numberToProcess = (Integer)objFromVector;
This code will throw an IllegalCastException if the Vector contains something that isn't an Integer object. If you are worried about that you can encompass it in a try catch statement.
In your example you will presumably want to just loop through all the numbers in the Vector. You also might want to be more prescriptive about what objects your Vector can contain (called 'Generics', which is similar to C templating). Here's what it might look like:
Vector<Integer> myVector = new Vector<Integer>();
// Add stuff to the Vector
for (Integer number : myVector)
{
// Do stuff with the number
}
The foreach and Generics constructs were only added in Java SDK 1.5, so you can't use them if you want to run on an earlier Java SDK.

Related

How to create a generic number of objects?

I am currently thinking about how to create n objects of type x in Java.
Thought experiment: You want to create all entries from a specific database table as an object.
The number of entries are given by counting them.
The object to be created is a model of a table entry.
My current strategy would be to create Lists foreach column.
After that, I would create an Object by looping through the Lists, append it to a HashSet and continue with the next row.
But probably there is a problem with the references, because the created objects would have the same name and if I remember right, I would overwrite the pointer by creating another object in this case. So it's the question if the HashSet still contains the old reference or not.
Besides this solution would be very ineffective cause of the number of loops.
Pseudocode
HashSet for objects
lists of every column
iterate through lists
create object with values at position i of loop
append object to HashSet
If you have a clue about to solve the pointer problem or if it does not exist, I would be glad about your answer. Moreover, I would be grateful for more suited solutions.
PS: I did not found any design pattern for this use case
If I'm correctly understanding the "pointer problem" to which you refer, it does not exist. I think you may have some misconceptions about how references, as they are properly called in Java, work.
Take the following code
Set<MyObject> mySet = new HashSet<>();
MyObject myOb;
myOb = new MyObject("Object #1"); // 1
mySet.add(myOb); // 2
myOb = new MyObject("Object #2"); // 3
mySet.add(myOb); // 4
At the lines marked // 1 and // 2 we create a MyObject object with the data "Object #" and add it into a Set; the variable myOb references the object we've just created.
If we were to print the contents of the set at this point, we'd see
{["Object #1"]}
At line // 3, we create another new MyObject object, this time with the data "Object #2", and assign myOb to reference it.
But wait! We've just added myOb (which was referencing an object with the data "Object #1") to the set, and now we're changing myOb to reference a different object. Does that mean our set suddenly looks like:
{["Object 2"]}
No, it doesn't, because what was added to the set was not myOb itself, but the rather the myObject object that myOb happened to be referencing at the moment that mySet.add(myOb) was called. All the set received was a reference to a MyObject instance; it hasn't the slightest clue that the reference happened to be stored in the variable myOb.
Thus we can make myOb reference (or "point to", if you prefer) any other MyObject object (or even the same object again) without affecting the set in the slightest.

Is there any functional difference between direct sub array copy into 2-D array and using for loop in java

I have written 2-pieces of code to copy sub-array elements of a 2-D array as below
First Method:
String [][] actual = new String[5][5];
String [] arrayToCopy = {"1","2","3","4","5"};
actual[0] = arrayToCopy;
Second Method:
String [][] actual = new String[5][5];
String [] arrayToCopy = {"1","2","3","4","5"};
for(int i=0;i<5;i++)
actual[0][i] = arrayToCopy[i];
Is there any difference in functionality between above two methods as they are generating same output when I print the 2-D array?
One difference that you will need to worry about is that when you say
actual[0] = arrayToCopy;
You are actually not "copying" your array. Instead, you are replacing actual[0]
with a reference to arrayToCopy. If you change the array from either variable, the change will be reflected in the other. You can see it yourself:
System.out.println(actual[0][0]); // prints "1"
arrayToCopy[0] = "5";
System.out.println(actual[0][0]); // prints "5"
In the second approach, actual[0] and arrayToCopy reference different arrays, and you are actually "copying" elements from one array to the other. Changing one, will not change the other.
As for your question, does it differ in "functionality"? Depends on what you mean, but if the data is read-only then it's not that big of a deal. It only becomes a problem when you can modify the data and you're not careful and start changing things that shouldn't be changed.
In Java, assignments are by reference (except in primitive types (boolean, int, float, double, short, char, byte, long). When you do something like your first attempt, you don't copy the array, you are just referencing it in another variable.
actual[0] = arrayToCopy;
If you try doing something like that:
actual[0][3] = 5;
System.out.println(arrayToCopy[3]);
You will find 5. Any change happens to one, is reflected on the others.
But your second attempts copies the array.
If you want performant copying, consider using System.arrayCopy https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#arraycopy(java.lang.Object,%20int,%20java.lang.Object,%20int,%20int)
If you want performant programming and your array isn't shared between different objects, you could use the referencing solution (your first one).
But if you want to be in the safe side, or you worry about threading and data sharing between different objects, try copying.

What's more efficient and compact: A huge set of linkedlist variables or a two-dimensional arraylist containing each of these?

I want to create a large matrix (n by n) where each element corresponds to a LinkedList (of certain objects).
I can either
Create the n*n individual linked lists and name them with the help of eval() within a loop that iterates through both dimensions (or something similar), so that in the end I'll have LinkedList_1_1, LinkedList_1_2 etc. Each one has a unique variable name. Basically, skipping the matrix altogether.
Create an ArrayList of ArrayLists and then push into each element a linked list.
Please recommend me a method if I want to conserve time & space, and ease-of-access in my later code, when I want to reference individual LinkedLists. Ease-of-acess will be poor with Method 1, as I'll have to use eval whenever I want to access a particular linked list.
My gut-feeling tells me Method 2 is the best approach, but how exactly do I form my initializations?
As you know the sizes to start with, why don't you just use an array? Unfortunately Java generics prevents the array element itself from being a concrete generic type, but you can use a wildcard:
LinkedList<?>[][] lists = new LinkedList<?>[n][n];
Or slightly more efficient in memory, just a single array:
LinkedList<?>[] lists = new LinkedList<?>[n * n];
// Then for access...
lists[y * n + x] = ...;
Then you'd need to cast on each access - using #SuppressWarnings given that you know it will always work (assuming you encapsulate it appropriately). I'd put that in a single place:
#SuppressWarnings("unchecked")
private LinkedList<Foo> getList(int x, int y) {
if (lists[y][x] == null) {
lists[y][x] = new LinkedList<Foo>();
}
// Cast won't actually have any effect at execution time. It's
// just to tell the compiler we know what we're doing.
return (LinkedList<Foo>) lists[y][x];
}
Of course in both cases you'd then need to populate the arrays with empty linked lists if you needed to. (If several of the linked lists never end up having any nodes, you may wish to consider only populating them lazily.)
I would certainly not generate a class with hundreds of variables. It would make programmatic access to the lists very painful, and basically be a bad idea in any number of ways.

Copying data into a reference in java (lack of pointer problem)

So I have an ArrayList in java. And what I'm doing is creating a new list with updated values. But I want to put those new values into the original ArrayList. This is important because I'm passing the original arraylist reference to an object that I no longer have access to, but I need to keep its contents up to date. Is there any way to make java copy the contents into a current reference? I hope that makes sense.
Also, I'd rather not clear the original arraylist and then loop through it pushing the new contents into it.
I need to do something like this:
ArrayList a;
ArrayList *b = a;
//pass b (the pointer) to something
ArrayList c;
*b = c;
I really hope I got that (pseudo) c++ code correct or I'll look pretty stupid =P
I can see how I'm not being clear, it's kind of complicated (this is in android so it's across a couple activities) so let me see if I can get my point across better.
Class1{
ArrayList a;
method1(){
a = Class2.getA();
method_that_uses_a(a);
}
}
Class2{
ArrayList getA(){
ArrayList a = new ArrayList
a = getDataFromWebsite();
return a;
}
Class1's method1() gets called periodically by another portion of code. But I need the reference to a stay the same, but the contents to change to the new contents.
I think your question is unclear, what do you mean by
"And what I'm doing is creating a new list with updated values. But I want to put those new values into the original ArrayList. This is important because I'm passing the original arraylist reference to an object that I no longer have access to, but I need to keep its contents up to date. Is there any way to make java copy the contents into a current reference? I hope that makes sense."
When you do
List a = new ArrayList
List b = a
you have one ArrayList object, and two references to the object, a and b.
Also note that there is an addAll method that you can use to add members of one collection to another collection. Note that I believe addAll does not do a deep copy, so if you use it both lists have copies of the same reference. So if list a has references a1, a2, a3, and you do b.addAll(a), b now has references to the objects that a1...a3 point to...
The array classes all expose public clone() methods, however, so if a
shallow copy of the array is sufficient then
return (ElementType[]) myArray.clone();
Makes for a nice, simple, easy to read paradigm. If "ElementType" is a
primitive type then there is no distinction between shallow and deep
copying, and if it is immutable then performing a deep copy would be
wasteful. In some other circumstances a shallow copy is what you would
want anyway (you want the receiver to be able to mutate the returned
array elements with effects visible to the host object).
If you find that you really do want to make a deep copy of the array
then you might want to consider whether your design can be improved; it
is not necessarily so, but I wouldn't be surprised.
In Java as I hope you;ve found out by now, all variables are references. Among other things this means that unless they are assigned to an object they don't 'point' at anything. You need to write:
ArrayList a = new ArrayList();
or a doesn't 'point to' an actual object - it's just null.
If you write:
ArrayList a = new ArrayList();
ArrayList b = a;
modify(b);
ArrayList c = b;
then there is only one ArrayList. All the variables a, b and c refer to it. Any modifications done in the 'modify' method apply to it, and will be reflect in the state of a, b and c.
You're C++ code says this:
ArrayList a; //make arraylist
ArrayList *b = a; //set b to point to same arraylist as a
//pass b somewhere
ArrayList c; //make arraylist
*b = c; //variable b in THIS PROGRAM now points to c. arraylist is unchanged.
You want to update the arraylist, not the pointer to it, as that pointer only 'exists' in the current context. The code you passed the arraylist to doesn't give a darn if a pointer back in who-knows-where now points to the same arraylist that its using. It's the actual object the other code cares about. To update that object, you can just call methods on it, like a.add(bar)
BUT there's more to it. If you call a function you don't control (now known as foo) and pass it an arraylist, that's all fine. But if you want to update it from the code calling foo, you run into issues. Imagine if an object you were working with could change randomly at any time. All sorts of bad stuff could happen. If you really need this capability (and we can help you judge if you do), look into the topic of threading.

Dynamic array declaration in java

can anyone tell me the error in this java declaration String[][] t=new String[15][15]; this works fine and if i use String[][] t=new String[][]; because i need to declare the variable t as dynamic as i am not sure how much values i am going to store in t.
Use ArrayList (or other array object who can handle any number of objects). A java array always has a fixed length since some memory will be reserved for the array.
ArrayList creates such array as well to store the objects. Of you add more abjects as the current reserved size of the array than ArrayList will create a new bigger array (+50% if i'm correct). There are some other implementations that act a bit different (for example they create a new array 100% of the original one when the array is full. If performance is really important for you than you can look into this.
ArrayList<ArrayList<String> t = new ArrayList<ArrayList<String>();
void fill() {
ArrayList<String> t2 = new ArrayList<String>();
t2.add("somestring");
String s = "someotherstring";
t2.add(s);
t.add(t2);
}
If you don't know how big it needs to be just declare it as
String[][] t;
and once you know how big it needs to be you can do (before trying to use the array)
t = new String[15][15];
If you're never sure how big the array need to be, you'll need to use something like a List of Lists.
List<List<String>> t = new ArrayList<List<String>>;
public void add(String str, int row, int col) {
while (row >= t.size())
t.add(new ArrayList<String>());
List<String> row_list = t.get(row);
while (col >= row_list.size())
row_list.add("");
row_list.set(col, str);
}
In Java array objects are always of fixed length. Once you have allocated them you cannot change their size. An array variable can be made to point to different array objects of different size. So you can allocate:
String[][] t;
which doesn't point to an object and allocate an object later once you know the size:
int n1,n2;
// calculate n1,n2
t = new String[n1][n2];
If you need a structure where the size can change you are much better off using ArrayList, which can be dynamically resized.
Declare it as String [][]t = null;
And Reinitialize it with actual length once you get it.
t=new String[x][y];
As bemace said, just because you are declaring the variable doesn't mean you have to initialize it immediately.
As Mark said, arrays have a fixed size. Once an array is initialized(not declared, initialized) it has a fixed size.
So, there are two possibilities:
Either you will know how big the array needs to be before you need to start using it, in which case you can simply delay your initialization as suggested by bemace.
Or you won't know how big it needs to be before you start using it, in which case you need to use a dynamically sized data structure(s). Check out the Java Collections API:
tutorial
api reference
There are several good answers already, but it has now been revealed in a comment to Mark Baijens' answer that the purpose of this question is that raju need a key to multi-value mapping.
Mark followed up that comment by suggesting raju use a HashMap<String, String> hashMap = new HashMap<String, String>(); — however that only works for a single key-value pair.
What raju needs is a
Map<String, Collection<String>> t
= new HashMap<String, List<String>>();
Adding the first value for a key requires initialization of a List for that bucket, while adding additional values requires fetching the existing list and adding the new value.
Note I used Collection<String> in the declaration, so it could be a List if the order of values is important, or it could be a Set to prevent duplicate values under the same key.
This would probably be best implemented as a Class itself, perhaps
public class MultiValueMap<K, V> extends Map<K, V>
{
...
}
so the initialization of the List on the first put(key, value) and the subsequent .add(value) to the list could be hidden in the implementation.

Categories

Resources