How does Java store objects in a List? - java

I have to work with an existing application and there is a List which stores all rendered objects in order to remove them later if the gui changes.
This is the List:
private List<Component> registeredComponents = new ArrayList<Component>();
Now I'm wondering if Java only stores references to the objects (ZK components) or if it does store a copy of the objects. The question is if I should remove this.

The list will contain references only. This holds for all types of collections, not only ArrayLists.
In Java there's actually no way to "get hold of" the object itself. When you create a new object all you get is a reference to it (and there's no way to "dereference" it by using for instance a * operator as in C++).

The List stores references to the objects, not a copy. The object instances are shared with anyone else who happens to have another reference to them.
As for wanting to remove this, if you have another way to remove the objects from the GUI later (maybe you can query a parent component or something), the List may be redundant. But even if it is, there is probably not much overhead here, and not having it might be complicating your program.

Related

Java: Wrapping objects in some type of collection to store duplicates in a set

I want to make a set of some type of collection (not sure which one yet) as a way of "storing duplicates" in a set. For example if I wanted to add the integer 5 with 39 additional copies I could put it into an arraylist at index 39. Thus if I were to get the size of the arraylist, I would know how many copies of 5 existed within the set.
There are a few other ways I could implement this but I have yet to decide on one. The main issue I'm having with implementing this is that I'm not sure how I can "dynamically" make arraylists (or whatever collection I may end up using) so that whenever someone were to call mySet.add(object), the object is first inserted into a unique arraylist then into the set itself.
Can anyone give me some ideas on how I could approach this?
EDIT:
Sorry I should have been more clear in my question. The point of the code that I'm writing is that we have a set-like collection that allows duplicates. And yes some of the associated methods will be re-written/will have to be re-written. Also my code should be written under the assumption that we do not know what type of object is being inserted(only one data type per set though) nor how many instances of the same object will be added nor how many different unique objects will be added.
I would rather go for using a Map like
HashMap list <Object, Integer>
where Object is the Object that you want to count and Integer is the count
You could try guava's MultiSet, I think it's what you want.
It can store the count of each object. What you need to do is just
multiSet.put(object);
And if it is put for the first time, like you said, a new list will be created, or its count will added by one.

" Suppose you are passing or returning an array of references to mutable objects to/from a method..."

"Suppose you are passing or returning an array of references to mutable objects to/from a method. Is it safe to make a reference copy only? Is it safe to make a shallow copy?"
This is a study question that was given to my class and the answer is "Neither one is safe. Only a deep copy is safe in this case."
Why is this?
"Safe" can mean a lot of things, but in your particular context it is about the safety of "your" private data (the text refers to "you" as a writer of some Java class). Your private data cannot be safe if you let the client of your class access and modify it behind your back.
Therefore:
if you return an array of mutable objects, you must make copies of all those objects and return them in a new array;
if you get an array of mutable objects passed in, you must again copy them all and put them into a new array—because your client already has references to the objects he passed in.
In practice, all this is a lot of CPU work and takes memory, so it is rarely done. You either design everything to be immutable—or else live with the danger inherent to mutable objects.
If your objects are mutable that means that any client with a reference to them can modify them. This can lead to race conditions, deadlocks and other un-fun behavior. However, if you make a deep copy of your objects right before using them, you will effectively be working with a snapshot of the objects. This ensures no other client is able to modify them, eliminating any concurrency or correctness concern.
In the first case both the original array elements and the objects can be modified. In the second case only the objects can be modified, as we no longer have access to the original array. If you perform a deep copy we are working with entirely different arrays and objects, so of course it's safe.

Avoiding duplicate objects in Java deserialization

I have two lists (list1 and list2) containing references to some objects, where some of the list entries may point to the same object. Then, for various reasons, I am serializing these lists to two separate files. Finally, when I deserialize the lists, I would like to ensure that I am not re-creating more objects than needed. In other words, it should still be possible for some entry of List1 to point to the same object as some entry in List2.
MyObject obj = new MyObject();
List<MyObject> list1 = new ArrayList<MyObject>();
List<MyObject> list2 = new ArrayList<MyObject>();
list1.add(obj);
list2.add(obj);
// serialize to file1.ser
ObjectOutputStream oos = new ObjectOutputStream(...);
oos.writeObject(list1);
oos.close();
// serialize to file2.ser
oos = new ObjectOutputStream(...);
oos.writeObject(list2);
oos.close();
I think that sections 3.4 and A.2 of the spec say that deserialization strictly results in the creation of new objects, but I'm not sure. If so, some possible solutions might involve:
Implementing equals() and hashCode() and checking references manually.
Creating a "container class" to hold everything and then serializing the container class.
Is there an easy way to ensure that objects are not duplicated upon deserialization?
Thanks.
After deserialization of the second list you could iterate over it's the elements and replace duplicates by a reference to the first list.
According to 3.7 The readResolve Method the readResolve() method is not invoked on the object until the object is fully constructed.
I think that sections 3.4 and A.2 of the spec say that deserialization strictly results in the creation of new objects, but I'm not sure. If so, some possible solutions might involve: ...
2, Creating a "container class" to hold everything and then serializing the container class.
I read these statements as "if I my understanding about deserialization always creating new objects is incorrect, then solution #2 of writing both lists wrapped in a container class to a single stream is an acceptable solution."
If I am understanding you correctly, this means you think writing out through a single container containing both lists won't work because it will still result in duplicate objects ("strictly results in ... new objects"). This is incorrect. When writing out the graph of objects (your wrapper class), each object is only serialized once, no matter how many occurrences in the graph. When the graph is read back in, that object is not duplicated.
http://java.sun.com/javase/6/docs/api/java/io/ObjectOutputStream.html
The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also. Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written.
So, if you can, use option #2.
Creating a "container class" to hold everything and then serializing the container class.
You can override the readResolve() method to replace what's read from the stream with anything you want.
private Object readResolve() throws ObjectStreamException {
...
}
This is typically used for enforcing singletons. Prior to Java 5 it was also used for typesafe enums. I've never seen it used for this but scenario but I guess there's no reason it couldn't be.
Now this will work with individual objects that you control but I can't see how you'd make it with a List. It could ensure that the objects returned in that list aren't duplicated (by whatever criteria you deem).

How do I copy an arraylist from one class to another in Java?

I understand that in order to copy an arraylist and have two lists independent of one another you must use a deep copy (copying the objects from one list to another not just the references), however is there a way this can be done cross-class?
For example; I am calling Class2 from Class1. In Class2 objects are added to an ArrayList of custom objects upon an event. I would like to be able to transfer this ArrayList to Class1 but whenever I try I get a NullPointer.
Any clues??
This is highly indicative of a design flaw.
See if you can't accomplish the same goal by wrapping your list in a class, sharing the class and using it to control access to the list.
The only case where this wouldn't just outright work is if your two classes must modify the list independently.
If this is a requirement, then I would probably hand a different instance of the wrapper class to each modifying class (with a reference to the same source list), then have a way for newly added data to be tagged with an ID referring to the original class--that way when you query, the wrapper would only return untagged items (items that were part of the original shared list) and items tagged with it's own ID.
Either that or the wrapper class could contain a second list and when queried, return the combined results of the original and second lists.
I've almost never wanted a deep copy. It happens, but it's quite rare.
If you post more info, maybe we can be more specific in helping with the redesign.
ALSO: (Edit)
Chances are that the copied array list isn't your problem--it's probably that it wasn't TRULY a deep copy. For a deep copy, it means you implement a copy method (I believe they are supposed to be called .clone(), I never use this stuff--as I said, it's bad juju) for each object in the array list, then you call your copy method on each one to get the new copy in your next list.
Furthermore, any objects referenced by your copied object should probably be cloned as well. "Deep" means all the way down the tree.
I'm guessing you're failing somewhere in the process.
I'd really like to hear why you feel you need a copy instead of a reference.
My suggestion is for you to create a getArray() method and call it from the other class. This method should create a copy of the ArrayList because you should not "transfer" variables within classes; always with get() method so OO paradigm stays intact.
Do something like this:
Class 1
public ArrayList<Object> getArray() {
ArrayList<Object> aux = new ArrayList<Object>();
for(Object x : list) //object is the string, int, etc...
aux.add(x.clone()) //assuming the Object has a clone method!
return aux;
}
On Class 2, just call this method. Then just look at the test from the other answer about the null exception, should work.
Hope it helps.

Is there an expandable list of object references in Java?

In Java, we can always use an array to store object reference. Then we have an ArrayList or HashTable which is automatically expandable to store objects. But does anyone know a native way to have an auto-expandable array of object references?
Edit: What I mean is I want to know if the Java API has some class with the ability to store references to objects (but not storing the actual object like XXXList or HashTable do) AND the ability of auto-expansion.
Java arrays are, by their definition, fixed size. If you need auto-growth, you use XXXList classes.
EDIT - question has been clarified a bit
When I was first starting to learn Java (coming from a C and C++ background), this was probably one of the first things that tripped me up. Hopefully I can shed some light.
Unlike C++, Object arrays in Java do not store objects. They store object references.
In C++, if you declared something similar to:
String myStrings[10];
You would get 10 String objects. At this point, it would be perfectly legal to do something like println(myStrings[5].length); - you'd get '0' - the default constructor for String creates an empty string with length 0.
In Java, when you construct a new array, you get an empty container that can hold 10 String references. So the call:
String[] myStrings = new String[10];
println(myStringsp[5].length);
would throw a null pointer exception, because you haven't actually placed a String reference into the array yet.
If you are coming from a C++ background, think of new String[10] as being equivalent to new (String *)[10] from C++.
So, with that in mind, it should be fairly clear why ArrayList is the solution for an auto expanding array of objects (and in fact, ArrayList is implemented using simple arrays, with a growth algorithm built in that allocates new expanded arrays as needed and copies the content from the old to the new).
In practice, there are actually relatively few situations where we use arrays. If you are writing a container (something akin to ArrayList, or a BTree), then they are useful, or if you are doing a lot of low level byte manipulation - but at the level that most development occurs, using one of the Collections classes is by far the preferred technique.
All the classes implementing Collection are expandable and store only references: you don't store objects, you create them in some data space and only manipulate references to them, until they go out of scope without reference on them.
You can put a reference to an object in two or more Collections. That's how you can have sorted hash tables and such...
What do you mean by "native" way? If you want an expandable list f objects then you can use the ArrayList. With List collections you have the get(index) method that allows you to access objects in the list by index which gives you similar functionality to an array. Internally the ArrayList is implemented with an array and the ArrayList handles expanding it automatically for you.
Straight from the Array Java Tutorials on the sun webpage:
-> An array is a container object that holds a fixed number of values of a single type.
Because the size of the array is declared when it is created, there is actually no way to expand it afterwards. The whole purpose of declaring an array of a certain size is to only allocate as much memory as will likely be used when the program is executed. What you could do is declare a second array that is a function based on the size of the original, copy all of the original elements into it, and then add the necessary new elements (although this isn't very 'automatic' :) ). Otherwise, as you and a few others have mentioned, the List Collections is the most efficient way to go.
In Java, all object variables are references. So
Foo myFoo = new Foo();
Foo anotherFoo = myFoo;
means that both variables are referring to the same object, not to two separate copies. Likewise, when you put an object in a Collection, you are only storing a reference to the object. Therefore using ArrayList or similar is the correct way to have an automatically expanding piece of storage.
There's no first-class language construct that does that that I'm aware of, if that's what you're looking for.
It's not very efficient, but if you're just appending to an array, you can use Apache Commons ArrayUtils.add(). It returns a copy of the original array with the additional element in it.
if you can write your code in javascript, yes, you can do that. javascript arrays are sparse arrays. it will expand whichever way you want.
you can write
a[0] = 4;
a[1000] = 434;
a[888] = "a string";

Categories