Binding a list in java - efficiently - java

I have an object myObject which contains a property called myThing. The object myThing has an ArrayList and a property list which is connected to it. I have some JLabel myLabel which is bound to the list property.
To make this work, when the firePropertyChange is done, I have to make a clone of the list so that I pass a PropertyChangeEvent I have an old list and a new list to pass. This is very inefficient. Is there some way I should be doing this without the clone, that still allows me to bind properties?
Lists have been the bane of my existence lately.

I think cloning the List is the way to go in your case. You know, cloning a list only clone its structure, not all the members it contains, so its not "that" inefficient.

I think you should be take care of list clone.
it is a shallow copy of this ArrayList instance, but the elements themselves are not copied.
so, if you change copied ArrayList's element's property will be reflect to original ArrayList's element.
if you want your programs used ArrayList split, you should be rewrite ArrayList's clone method, use deeply copy.

Related

Immutable list in .NET: Why are you allowed to add and remove items?

In C#, I just got the need of having an immutable list, meaning that the list can not be changed.
Much like in Java's immutable list: https://www.geeksforgeeks.org/immutable-list-in-java/
From there:
If any attempt is made to add null element in List,
UnsupportedOperationException is thrown.
Now, with .NET (at least with Core 2.2) there is also an immutable list, documented here.
They say (emphasis mine):
When you add or remove items from an immutable list, a copy of the
original list is made with the items added or removed, and the
original list is unchanged.
So, this implementation basically allows changing the list (by getting a manipulated copy each time), as opposed to the java understanding, and what's more, it will mostly go undetected clogging memory.
What's the point in having an immutable list that supports add and remove methods in the first place?
The problem for me here is, that users of my code would get a list, immutable presumably, but out of neglectance would happily add items, which will never made it to the original "repository". This will cause confusion.
I guess the (only) way to go here, to forbid manipulation entirely, and make it clear to the code user, would be to use the IEnumerale interface?
What's the point in having an immutable list that supports add and
remove methods in the first place?
No one but to be conform with the List contract, the implementation even immutable will expose every List methods.
After you have two ways to cope with these modification methods : throwing an exception or guaranteeing the immutability by creating and returning a new List at each modification.
About :
I guess the (only) way to go here, to forbid manipulation entirely,
would be to use the IEnumerale interface?
Indeed, in Java you use Iterable (that is close enough) when you want to be able to manipulate a collection of things without a way to change it.
As alternative you can also use an array.
As you said: "a copy of the original list is made with the items added or removed, and the original list is unchanged.".
So you can add/remove elements and a new list is made with the changes. The original list is unchanged.
What's the point in having an immutable list that supports add and remove methods in the first place?
First think of this: What is the point of an immutable list that doesn't support adding or removing items in any way? There is nothing particular useful to that. You can use array for that.
Now back to your question. The list is immutable, so consumers can't change the instance itself which was provided through some other method or class. The backing storage can't be altered by consumers! But the producer of the immutable list can 'alter' the backing store by creating a new immutable list and assigning that to the original variable. Isn't that useful!

Unmodifiable List in java peculiar behaviour [duplicate]

From ImmutableList javadocs:
Unlike
Collections.unmodifiableList(java.util.List),
which is a view of a separate
collection that can still change, an
instance of ImmutableList contains its
own private data and will never
change. ImmutableList is convenient
for public static final lists
("constant lists") and also lets you
easily make a "defensive copy" of a
list provided to your class by a
caller.
Does it mean that:
if I have ImmutableList of Dimension objects (for example) then I can't change any Dimension object in it?
and if I have Collections.unmodifiableList (list) of Dimension objects then I can't only add or delete any object but I can change them (for example call setDimension(width, height) method)?
No, the immutability is only applied to the amount and references of the objects in the Collection, and does not address the mutability of objects you put in the Collection.
What Immutable list gains over the standard JDK Collections.unmodifiableList is that by using ImmutableList you are guaranteed that the objects referenced, their order and the size of the list cannot change from any source. With Collections.unmodifiableList if something else has a reference to the underlying list, that code can modify the list even though you have a reference to an unmodifiable list.
If, however, you want true immutability, you have to fill the list with immutable objects.
Using Collections.unmodifiableList creates a wrapper around your List. if the underlying list changes, so does your unmodifiableList's view.
As the documentation says, Google's code creates a copy. It's a more expensive computation and consumes more memory, but if someone alters the original list, it cant affect the ImmutableList.
Neither of these will prevent you from changing an object in a list, or it's fields, or fields of fields, etc.
ImmutableList is similar to Collections.unmodifiableList( new ArrayList( list ) ) . Note that the newly created ArrayList is not assigned to a field or variable.
No, the contained individual objects can still be modified. A collection is really only storing references to the contained objects, not a full copy of every object.
You can modify the list by modifying the parent Collection you called Collections.unmodifiableList(list) on. But yes, you CAN use setDimension to change a stored list element.
You might also want to take a look at this question (What's the difference between Collections.unmodifiableSet() and ImmutableSet of Guava).

Best way to transfer value from an ArrayList to another

With 2 ArrayList, I was wondering if the best way from transforming the 1st one into a "copy" of the second one is to go like
myFirstArray.clear();
myFirstArray.addAll(mySecondArray);
or
myFirstArray = mySecondArray.clone();
What are the main differences between those two method, which on is preferrable and is there another "easier" or "cleaner" solution. Thanks for any tips
EDIT : I use this copy for replacing an Array of item im currently working with the one where I store the item I'll work with in the next loop. At the end of the loop I replace my currentArrayList with my futurArrayList and I clear my futurArraylist in order to add new item in it (i hope its clear enough)
The first one replaces the content of the list by another content. The second one creates another ArrayList instance, leaving the previous one untouched.
If the list is referenced by some other object, and you want this other object to be untouched, use the second one. If you want the other object to also have the new content, use the first one.
If nothing else referenced the list, it doesn't matter much. The second one will reduce the memory used in case you replace the content of a huge list by a few elements.
In java, though clone is ‘intended’ to produce a copy of the same object it is not guaranteed.
Clone comes with lots of its and buts. So my first advice is to not depend on clones.
By default, java cloning is ‘field by field copy’ i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked. So, JVM when called for cloning, do following things:
If the class has only primitive data type members then a completely
new copy of the object will be created and the reference to the new
object copy will be returned.
If the class contains members of any class type then only the object
references to those members are copied and hence the member
references in both the original object as well as the cloned object
refer to the same object because of that cloned object changes are visible in original also.
Use that:
List<Object> first = ...
ArrayList<Object> second = new ArrayList<>(first);
I also suggest that you do not use clone() at all. It's better to use a copy constructor or some factory method. Take a look at here.
Of course in your case, with the ArrayList, it will work as expected, you will end up with a copy of the references.
Guava, guava, guava!
final List copied = ImmutableList.copyOf(originalList);

Can I get a reference to List<> object having a reference to one of its elements?

For example I have a reference to an mItem object of my List<mItem> mList collection. Is that possible to get a reference to mList using mItem?
The short answer is no. The items in a list don't know they are in a list. (Unless of course you add a reference to the list inside your mItem object.)
Short answer: no.
Adding an item to a list adds a reference to that object to the list. It does not affect the object itself.
You can check to see if an item is in a specific list, with mList.contains(mItem) which returns true if the item is in mList. Alternatively if you really need to, you could as others have suggested implement a version of List that informs each item that the list has a reference to that item. The overhead would be rather messy though.
Meta question: why do you need this functionality?
As jzd said... you can add a field to your mItem class (for example referenceHolder)
mItem(Object ref){
referenceHolder = ref;
}
class with List:
mList.add(new mItem(this));
something like that should work :) but its kind of weird ;), because normally "The items in a list don't know they are in a list. "
EDIT: and as said before - "One object should be a member of multiple collections" - so you would need to change type of my referenceHolder to some list or array, to make that able to happen.
EDIT2: that's just reference to object holding that list (if one object will have multiple lists, you wont be able to know witch of them is holding that sepecified mItem object), to reference to List itself you will need (as said in comment ;)) custom list implementation adding references to stored objects with this in add() method.
If you have a container for all you lists, you can call contains on each one to find which list the item is in.
Note: for a list you can have the same element multiple time, and across multiple list.
BTW: If you don't want duplicates in a list and don't care about the order of elements then a Set may be your best choice.

What is the difference between google's ImmutableList and Collections.unmodifiableList ()?

From ImmutableList javadocs:
Unlike
Collections.unmodifiableList(java.util.List),
which is a view of a separate
collection that can still change, an
instance of ImmutableList contains its
own private data and will never
change. ImmutableList is convenient
for public static final lists
("constant lists") and also lets you
easily make a "defensive copy" of a
list provided to your class by a
caller.
Does it mean that:
if I have ImmutableList of Dimension objects (for example) then I can't change any Dimension object in it?
and if I have Collections.unmodifiableList (list) of Dimension objects then I can't only add or delete any object but I can change them (for example call setDimension(width, height) method)?
No, the immutability is only applied to the amount and references of the objects in the Collection, and does not address the mutability of objects you put in the Collection.
What Immutable list gains over the standard JDK Collections.unmodifiableList is that by using ImmutableList you are guaranteed that the objects referenced, their order and the size of the list cannot change from any source. With Collections.unmodifiableList if something else has a reference to the underlying list, that code can modify the list even though you have a reference to an unmodifiable list.
If, however, you want true immutability, you have to fill the list with immutable objects.
Using Collections.unmodifiableList creates a wrapper around your List. if the underlying list changes, so does your unmodifiableList's view.
As the documentation says, Google's code creates a copy. It's a more expensive computation and consumes more memory, but if someone alters the original list, it cant affect the ImmutableList.
Neither of these will prevent you from changing an object in a list, or it's fields, or fields of fields, etc.
ImmutableList is similar to Collections.unmodifiableList( new ArrayList( list ) ) . Note that the newly created ArrayList is not assigned to a field or variable.
No, the contained individual objects can still be modified. A collection is really only storing references to the contained objects, not a full copy of every object.
You can modify the list by modifying the parent Collection you called Collections.unmodifiableList(list) on. But yes, you CAN use setDimension to change a stored list element.
You might also want to take a look at this question (What's the difference between Collections.unmodifiableSet() and ImmutableSet of Guava).

Categories

Resources