I need some class/interface name that describes an immutable, ordered set (in input order, like LinkedHashSet). I can of course just use the class like this:
class Foo {
public final Set<Long> frozenOrderedSet;
public Foo(List<Long> input) {
frozenOrderedSet = Collections.unmodifiableSet(new LinkedHashSet(input));
}
}
But this would not clarify my approach. I would like to make it clear to everyone reading the source that the Set is unmodifiable and unique while maintaining it's order with for(Long l : set){}.
Guava's ImmutableSet provides a high-performance, immutable Set with reliable, user-specified iteration order. There are also variations like ImmutableSortedSet.
The simplest way would be extend Set to create a custom immutable Set.
public CustomImmutableSet(){ return Collections.unmodifiableSet(new
LinkedHashSet(input)); }
This way it will make it clear to everyone reading the source that the Set is unmodifiable and unique
Bozho in question Java Immutable Collections:
Unmodifiable collections are usually read-only views (wrappers) of
other collections. You can't add, remove or clear them, but the
underlying collection can change.
Immutable collections can't be changed at all - they don't wrap
another collection - they have their own elements.
Here's a quote from guava's ImmutableList
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.
So, basically, in order to get an immutable collection out of a
mutable one, you have to copy its elements to the new collection, and
disallow all operations.
So Basically you might create subclass of class TreeSet and override all :add, remove etc. methods to just throw an Exception saying that this is immutable collection. Also you would have to create copying constructor in this class with one parameter TreeSet setToCopyFrom.
Related
Is it possible to find out if some a list is fixed size or not?
I mean, for example this code:
String[] arr = {"a", "b"};
List<String> list = Arrays.asList(array);
returns fixed size List backed by an array. But is it possible to understand programmatically if List is fixed-size or not without trying to add/remove elements and catching the exception? For example:
try {
list.add("c");
}
catch(UnsupportedOperationException e) {
// Fixed-size?
}
A list created from a String[] by
List<String> list = Arrays.asList(array);
will have Arrays as enclosing class, while one created by for example new ArrayList() won't have the enclosing class. So the following should work to check if the List was produced as a result of calling Arrays.toList():
static <T> boolean wasListProducedAsAResultOfCallingTheFunctionArrays_asList(List<T> l) {
return Arrays.class.equals(l.getClass().getEnclosingClass());
}
Beware that this method relies on undocumented behavior. It will break if they added another nested List subclass to the Arrays class.
Is it possible to find out if some list is fixed size or not?
In theory - No. Fixed sizedness is an emergent property of the implementation of a list class. You can only determine if a list has that property by trying to add an element.
And note that a simple behavioral test would not reliably distinguish between a fixed sized list and a bounded list or a list that was permanently or temporarily read-only.
In practice, a fixed sized list will typically have a different class to an ordinary one. You can test the class of an object to see if it or isn't a specific class. So if you understand what classes would be used to implement fixed sized lists in your code-base, then you can test if a specific list is fixed sized.
For example the Arrays.asList(...) method returns a List object whose actual class is java.util.Arrays.ArrayList. That is a private nested class, but you could use reflection find it, and then use Object.getClass().equals(...) to test for it.
However, this approach is fragile. Your code could break if the implementation of Arrays was modified, or if you started using other forms of fixed sized list as well.
No.
The List API is identical regardless of whether a List is expandable or not, something that was deliberate.
There is also nothing in the List API that allows you to query it to determine this feature.
You can't completely reliably determine this information by reflection, because you will be depending on internal details of the implementation, and because there is an unbounded number of classes that are potentially fixed-size. For example, in addition to Arrays.asList, there is also Arrays.asList().subList, which happens to return a different class. There can also be wrappers around the base list like Collections.checkedList, Collections.synchronizedList and Collections.unmodifiableList. There are also other fixed-size lists: Collections.emptyList, Collections.singletonList, and Collections.nCopies. Outside the standard library, there are things like Guava's ImmutableList. It's also pretty trivial to hand-roll a list for something by extending AbstractList (for a fixed-size list you need only implement the size() and get(int) methods).
Even if you detect that your list is not fixed-size, the specification of List.add allows it to refuse elements for other reasons. For example, Collections.checkedList wrappers throw a ClassCastException for elements of unwanted type.
And even if you know your list is expandable, and allows arbitrary elements, that doesn't mean you want to use it. Perhaps it's synchronized, or not synchronized, or isn't serializable, or it's a slow linked list, or has some other quality that you don't want.
If you want control over the type, mutability, serializability, or thread-safety of the list, or you want to be sure that no other code has kept a reference to it, the practice is that you create a new one yourself. It's not expensive to do so when unnecessary (memcopies are blazing fast), and it lets you reason more definitely about your code will actually do at runtime. If you'd really like to avoid creating unnecessary copies, try whitelisting instead of blacklisting list classes. For example:
if (list.getClass() != ArrayList.class) {
list = new ArrayList<>(list);
}
(Note: That uses getClass instead of instanceof, because instanceof would also be true for any weird subclasses of ArrayList.)
There are immutable collections in java-9, but there is still no common #Immutable annotation for example or a common marker interface that we could query to get this information.
The simplest way I can think of would be simply to get the name of the class of such an instance:
String nameList = List.of(1, 2, 3).getClass().getName();
System.out.println(nameList.contains("Immutable"));
but that still relies on internal details, since it queries the name of the common class ImmutableCollections, that is not public and obviously can change without notice.
This question already has answers here:
Java Immutable Collections
(7 answers)
Closed 9 months ago.
From the Collections Framework Overview:
Collections that do not support modification operations (such as add, remove and clear) are referred to as unmodifiable. Collections that are not unmodifiable are modifiable.
Collections that additionally guarantee that no change in the Collection object will be visible are referred to as immutable. Collections that are not immutable are mutable.
I cannot understand the distinction.
What is the difference between unmodifiable and immutable here?
An unmodifiable collection is often a wrapper around a modifiable collection which other code may still have access to. So while you can't make any changes to it if you only have a reference to the unmodifiable collection, you can't rely on the contents not changing.
An immutable collection guarantees that nothing can change the collection any more. If it wraps a modifiable collection, it makes sure that no other code has access to that modifiable collection. Note that although no code can change which objects the collection contains references to, the objects themselves may still be mutable - creating an immutable collection of StringBuilder doesn't somehow "freeze" those objects.
Basically, the difference is about whether other code may be able to change the collection behind your back.
Basically unModifiable Collection is a view, So indirectly it could still be 'modified' from some other reference that is modifiable. Also as its just a readonly view of annother collection , When the source collection changes unModifiable Collection will always present with latest values.
However immutable Collection can be treated as a readonly copy of another collection and can not be modified. In this case when the source collection changes , immutable Collection do not reflect the changes
Here is a testcase to visualise this difference.
#Test
public void testList() {
List<String> modifiableList = new ArrayList<String>();
modifiableList.add("a");
System.out.println("modifiableList:"+modifiableList);
System.out.println("--");
//unModifiableList
assertEquals(1, modifiableList.size());
List<String> unModifiableList=Collections.unmodifiableList(
modifiableList);
modifiableList.add("b");
boolean exceptionThrown=false;
try {
unModifiableList.add("b");
fail("add supported for unModifiableList!!");
} catch (UnsupportedOperationException e) {
exceptionThrown=true;
System.out.println("unModifiableList.add() not supported");
}
assertTrue(exceptionThrown);
System.out.println("modifiableList:"+modifiableList);
System.out.println("unModifiableList:"+unModifiableList);
assertEquals(2, modifiableList.size());
assertEquals(2, unModifiableList.size());
System.out.println("--");
//immutableList
List<String> immutableList=Collections.unmodifiableList(
new ArrayList<String>(modifiableList));
modifiableList.add("c");
exceptionThrown=false;
try {
immutableList.add("c");
fail("add supported for immutableList!!");
} catch (UnsupportedOperationException e) {
exceptionThrown=true;
System.out.println("immutableList.add() not supported");
}
assertTrue(exceptionThrown);
System.out.println("modifiableList:"+modifiableList);
System.out.println("unModifiableList:"+unModifiableList);
System.out.println("immutableList:"+immutableList);
System.out.println("--");
assertEquals(3, modifiableList.size());
assertEquals(3, unModifiableList.size());
assertEquals(2, immutableList.size());
}
Output
modifiableList:[a]
--
unModifiableList.add() not supported
modifiableList:[a, b]
unModifiableList:[a, b]
--
immutableList.add() not supported
modifiableList:[a, b, c]
unModifiableList:[a, b, c]
immutableList:[a, b]
--
I think the main difference is that the owner of a mutable collection might want to provide access to the collection to some other code, but provide that access through an interface that doens't allow the other code to modify the collection (while reserving that capability to the owning code). So the collection isn't immutable, but certain users aren't permitted to change the collection.
Oracle's Java Collection Wrapper tutorial has this to say (emphasis added):
Unmodifiable wrappers have two main uses, as follows:
To make a collection immutable once it has been built. In this case, it's good practice not to maintain a reference to the backing
collection. This absolutely guarantees immutability.
To allow certain clients read-only access to your data structures. You keep a reference to the backing collection but hand
out a reference to the wrapper. In this way, clients can look but not
modify, while you maintain full access.
An object is considered immutable if its state cannot change after it is constructed. After you create an immutable instance of a collection, it holds the same data as long as a reference to it exists.
One advantage of an immutable collection is that it is automatically thread safe. Collections containing immutable objects are automatically thread safe after construction. After you create such a collection, you can hand it to multiple threads, and they will all see a consistent view.
However, an immutable collection of objects is not the same as a collection of immutable objects. If the contained elements are mutable, then this may cause the collection to behave inconsistently or make its contents to appear to change.
In simple words, if you add a little immutability to something mutable, you get mutability. And if you add a little mutability to something immutable, you get mutability.
Immutable and Unmodifiable Are Not the Same :
The immutable collections behave in the same way as the Collections.unmodifiable... wrappers. However, these collections are not wrappers — these are data structures implemented by classes where any attempt to modify the data causes an exception to be thrown.
If you create a List and pass it to the Collections.unmodifiableList method, then you get an unmodifiable view. The underlying list is still modifiable, and modifications to it are visible through the List that is returned, so it is not actually immutable.
To demonstrate this behavior, create a List and pass it to Collections.unmodifiableList. If you try to add to that unmodifiable List directly, then an UnsupportedOperationException is thrown.
But, if you change the original List, no error is generated, and the unmodifiable List has been modified.
In this case, to make a collection immutable once it has been built, it's a good practice not to maintain a reference to the backing collection. This absolutely guarantees immutability.
Further, to allow certain clients read-only access to your data structures. You can keep a reference to the backing collection but hand out a reference to the wrapper. In this way, clients can look but not be able to modify, while you maintain full access.
So, an immutable collection can contain mutable objects, and if it does, the collection is neither immutable nor thread safe.
To quote The Java™ Tutorials:
Unlike synchronization wrappers, which add functionality to the wrapped collection, the unmodifiable wrappers take functionality away. In particular, they take away the ability to modify the collection by intercepting all the operations that would modify the collection and throwing an UnsupportedOperationException. Unmodifiable wrappers have two main uses, as follows:
To make a collection immutable once it has been built. In this case, it's good practice not to maintain a reference to the backing collection. This absolutely guarantees immutability.
To allow certain clients read-only access to your data structures. You keep a reference to the backing collection but hand out a reference to the wrapper. In this way, clients can look but not modify, while you maintain full access.
(emphasis mine)
This really sums it up.
If we are talking about JDK Unmodifiable* vs guava Immutable*, actually the difference is also in performance. Immutable collections can be both faster and more memory-efficient if they are not wrappers around regular collections (JDK implementations are wrappers).
Citing the guava team:
The JDK provides Collections.unmodifiableXXX methods, but in our opinion, these can be
<...>
inefficient: the data structures still have all the overhead of mutable collections, including concurrent modification checks, extra space in hash tables, etc.
// normal list
List list1 = new ArrayList();
list1.add(1);
// unmodifiable list
List list2 = Collections.unmodifiableList(list1);
// immutable list
List list3 = Collections.unmodifiableList(new ArrayList<>(list1));
list1.add(2);
list1.add(3);
System.out.println(list1);
System.out.println(list2);
System.out.println(list3);
Output:
[1, 2, 3]
[1, 2, 3]
[1]
Unmodifiable vs Immutable Collection
Create A modifiable map
Map<String, String> modifiableMap = new HashMap();
modifiableMap.put(“1”,”one”);
modifiableMap.put(“2”,”two”);
modifiableMap.put(“3”,”three”);
Create an unmodifiableMap out of modifiableMap
Map<String,String> unmodifiableMap = Collections.unmodifiableMap(modifiableMap);
unmodifiableMap.put(“4”,”Four”) ==>Exception
modifiableMap.put(“4”,”Four”); ==>Allowed, this will also reflect now in the unmodifiableMap , because unmodifiableMap() returns a wrapper around modifiableMap.
Create an immutableMap out of modifiableMap
Map<String,String> immutableMap = Collections.immutableMap(modifiableMap);
immutableMap.put(“5”,”Five”) ==>Exception
modifiableMap.put(“5”,”Five”); ==>Allowed, BUT this will NOT reflect now in the immutableMap, because immutableMap() returns a copy of the modifiableMap.
As noted above unmodifiable is not like immutable because an unmodifiable collection can be altered if for example an unmodifiable collection has an underlying delegate collection which is referenced by some other object and that object changes it.
Regarding immutable, it's not even well defined. However, generally it means that the object "will not change", but that would need to be defined recursively. For example, I can define immutable on classes whose instance variables are all primitives and whose methods all contain no arguments and return primitives. The methods then recursively allow the instance variables to be immutable and all methods to contain arguments that are immutable and that return immutable values. The methods should be guaranteed to return the same value over time.
Assuming that we can do that, there is also the concept thread safe. And you might be led to believe that immutable (or not changeble over time) also implies thread safe. However that is not the case and that is the main point I am making here that has not yet been noted in other answers. I can construct an immutable object that always returns the same results yet is not thread safe. To see this suppose that I construct an immutable collection by maintaining additions and deletions over time. Now the immutable collection returns its elements by looking at the internal collection (which may be changing over time) and then (internally) adding and deleting the elements that were added or deleted after creation of the collection. Clearly, although the collection would always return the same elements, it is not thread safe merely because it will never change value.
Now we can define immutable as objects that are thread safe and will never change. There are guidelines for creating immutable classes that generally lead to such classes, however, keep in mind that there may be ways to create immutable classes, that require attention to thread safety, for example, as described in the "snapshot" collection example above.
The Java™ Tutorials say the following:
Unlike synchronization wrappers, which add functionality to the
wrapped collection, the unmodifiable wrappers take functionality away.
In particular, they take away the ability to modify the collection by
intercepting all the operations that would modify the collection and
throwing an UnsupportedOperationException. Unmodifiable wrappers have
two main uses, as follows:
To make a collection immutable once it has been built. In this case,
it's good practice not to maintain a reference to the backing
collection. This absolutely guarantees immutability.
To allow certain clients read-only access to your data structures. You
keep a reference to the backing collection but hand out a reference to
the wrapper. In this way, clients can look but not modify, while you
maintain full access.
I think its a good enough explanation to understand the difference.
[Unmodifiable and Immutable]
Unmodifiable collection(object) can still be changed by changing origin object. It is possible using reference.
Java provides with several ways to create an Unmodifiable map:
Collections.unmodifiableMap()
Java 9 Map.of(), Map.ofEntries()
What is the use of Collections.singletonList() in Java? I understand that it returns a list with one element. Why would I want to have a separate method to do that? How does immutability play a role here?
Are there any special useful use-cases for this method rather than just being a convenient method?
The javadoc says this:
"Returns an immutable list containing only the specified object. The returned list is serializable."
You ask:
Why would I want to have a separate method to do that?
Primarily as a convenience ... to save you having to write a sequence of statements to:
create an empty list object
add an element to it, and
wrap it with an immutable wrapper.
It may also be a bit faster and/or save a bit of memory, but it is unlikely that these small savings will be significant. (An application that creates vast numbers of singleton lists is unusual to say the least.)
How does immutability play a role here?
It is part of the specification of the method; see above.
Are there any special useful use-cases for this method, rather than just being a convenience method?
Clearly, there are use-cases where it is convenient to use the singletonList method. Indeed, any program where you need to use an immutable list with one element is a valid use-case. (It takes roughly zero imagination to think of one.)
But I don't know how you would (objectively) distinguish between an ordinary use-case and a "specially useful" one ...
From the javadoc
#param the sole object to be stored in the returned list.
#return an immutable list containing only the specified object.
example
import java.util.*;
public class HelloWorld {
public static void main(String args[]) {
// create an array of string objs
String initList[] = { "One", "Two", "Four", "One",};
// create one list
List list = new ArrayList(Arrays.asList(initList));
System.out.println("List value before: "+list);
// create singleton list
list = Collections.singletonList("OnlyOneElement");
list.add("five"); //throws UnsupportedOperationException
System.out.println("List value after: "+list);
}
}
Use it when code expects a read-only list, but you only want to pass one element in it. singletonList is (thread-)safe and fast.
Here's one view on the singleton methods:
I have found these various "singleton" methods to be useful for passing a single value to an API that requires a collection of that value. Of course, this works best when the code processing the passed-in value does not need to add to the collection.
To answer your immutable question:
Collections.singletonList will create an immutable List.
An immutable List (also referred to as an unmodifiable List) cannot have it's contents changed. The methods to add or remove items will throw exceptions if you try to alter the contents.
A singleton List contains only that item and cannot be altered.
If an Immutable/Singleton collections refers to the one which having only one object and which is not further gets modified, then the same functionality can be achieved by making a collection "UnmodifiableCollection" having only one object. Since the same functionality can be achieved by Unmodifiable Collection with one object, then what special purpose the Singleton Collection serves for?
singletonList can hold instance of any object. Object state can be modify.
List<Character> list = new ArrayList<Character>();
list.add('X');
list.add('Y');
System.out.println("Initial list: "+ list);
List<List<Character>> list2 = Collections.singletonList(list);
list.add('Z');
System.out.println(list);
System.out.println(list2);
We can not define unmodifiableList like above.
Say you have a domain class that has an ArrayList attribute. What is the best practise when writing getters and setters for this type of instance (to avoid it being modified)?
public List getList() {
return Collections.unmodifiableList(list);
}
Return a List that is unmodifiable using the Collection.unmodifiableList() method:
Collections - Collection.unmodifiableList()
You can use Collections.unmodifiableList(). There are equivalents for the other major collections types.
Probably best practice is to move the code that operates on the list into the domain class. Possibly add a domain class that represents the sequence in a way appropriate to the domain.
If you are desperate to expose the list, then there is a choice:
return Collections.unmodifiableList(new ArrayList<Thing>(things));
// Bit big - shame there isn't a single method and class to do this.
return new ArrayList<Thing>(things);
// Do you really want to see client code modifying the list?
return Collections.unmodifiableList(things);
// Client may expecting a snapshot, modifications to the original will mess up.
Note if the elements of the list are mutable, you might want to do something about those too.
lweller's response is the what I would do in most cases, but it does throw an UnsupportOperationException which you may not want to deal with. In that case you might want to consider declaring a composite class, like UnmodifiableList, which contains a List of your choosing and exposes all the methods you want to support excluding those that would modify the list. This, of couse, would no longer be type compatible with the Collection interface.
Also consider making an immutable snapshot of the list.
public List getList() {
ArrayList copy = new ArrayList(this.list);
return Collections.unmodifiableList(copy);
}
We have a naming convention where
listXXX();
gives you a read-only list.
There might be setters/getters in addition to that with the proper access modifiers.
Use the guava ImmutableList class. Your getter should then follow the form:
public ImmutableList<T> getMyList() {
ImmutableList.copyOf(myList);
}
The advantage of guava over the Collections.unmodifiableList is that it reveals to the client that your colllection is immutable in the method signature, so there's very little chance of people mistakenly trying to add something to the collection.
Let's say I have a collection of objects which can be sorted using a number of different comparators based on the different fields of the object.
It would be nice to be able to know later on in the code which comparator was used to sort the Collection with and if it was ascending or descending. Is there anyway to do this elegantly instead of using a bunch of Booleans to keep track of things?
Not for the Collection interface, but if you use a SortedSet there's a comparator() method where you can ask for its comparator.
Otherwise you'll have to subclass the collection class you're using to add the accessors you need.
No there's nothing with the implementations that does this. You would need to track it yourself. You could subclass a Collection implementation to add fields which hold this information.
You could also map the implementations to metadata as you like with a Map -- in particular it seems like you want IdentityHashMap to do this, since you don't want two different collections to be compared for equality as keys with equals().
I would store a boolean (ascending/descending), and a reference to the Comparator used to sort, if that's what completely determines the sort. Or if it's sorted on field, store a String naming the field perhaps.
sure:
define methods for your decorated Collection<Foo>
public List<Comparator<Foo>> getComparators() { ... }
and
public int whichComparator() { ... }
that returns which Comparator is currently in use from the List. You could make it fancier with a Map and some sensible keys (say, enums - perhaps even enums which implement the comparators) if you're modifying which comparators might be used over the life of the object, but I think the above is a good enough start.