I have one customized list MyList that extends ArrayList, like this:
class MyList extends ArrayList<SomeParticularItem>{
[some methods...]
}
Since I have concurrent reads and writes to the list, I want to synchronize it:
MyList mylist = (MyList) Collections.synchronizedList(new MyList());
This seems to be fine, the .jar is build. Then, at runtime, I get:
java.util.Collections$SynchronizedRandomAccessList cannot be cast to MyList
Is there a better way (is there any way at all) to obtain a synchronized list of a list that inherits from some java.util.List?
Well why not make MyList synchronized, alternativly simply use the List interface
List mylist = Collections.synchronizedList(new MyList());
Edit:
You could of course let MyList extend Vector, since all of the Vectors methods are already synchronized you save some work.
The easiest way to do it would be to extend Vector instead of ArrayList. You could also synchronize the methods of MyList yourself if you wanted to keep it as an ArrayList.
Related
Take the following two lines of code:
List<String> listOfStrings = new ArrayList<>();
List<String> listOfStrings2 = new LinkedList<>();
I understand that it's good practice to program to Interfaces, however as a newbie, I'm trying to understand since we can only call List methods on both these instances, do they still "behave" like ArrayLists or LinkedLists (As in they perform like their respective classes when sorting/adding etc.)
Yeah they do behave like ArrayList or LinkedList, you can use this to save more different Lists (or your own objects) and call different implementations of the superclass's methods while iterating over an Array.
Both LinkedList and ArrayList implemented List, Collection, Iterable... interfaces, but they have different implementation of methods (like add(), remove(), etc. Arraylist and LinkedList will have different behavior/performance due to different implementations, when calling these methods).
Suppose I have a list of some class A defined as:
Object list = new ArrayList<A>();
I want to iterate over this. Is it possible? If yes then how? Even if I find the type of list using reflections then also I won't get to class A.
Also, note that I don't know what class A is. I just have list.
If you instantiate an ArrayList the way that you've shown (you want it to be treated as Object - this class doesn't allow iterating, classes implementing Iterable interface provide this function), and then you need to iterate over its elements, you can cast this list from Object to Iterable, that way iteration becomes available for list:
for(A a : (Iterable<A>) list) {
// do stuff
}
or when you need an Iterator iterating over elements of the list:
Object list = new ArrayList<A> ();
Iterator<A> it = ((Iterable<A>)list).iterator();
You might want to have a look at Java API Documentation of to read more about Iterable interface here.
Edit: This answer was edited thanks to helpful suggestions of Federico Peralta Schaffner and luk2302.
I found a way to do so. I did something like this:
List<?> list1 = (List<?>) list;
now I can iterate as,
for(Object o : list1) {
// code
}
So I'm aware that in order to synchronize an arrayList you need to use
Collections.SynchronizedList(new ArrayList());
But what if the synchronized arrayList is in one class and I want to have a refernce to it in several other classes, the multiple other classes containing the threads that will add to it. Would I do something like
List referenceToList = OtherClass.mainList;
// inside OtherClass would be List<String>mainList
= Collections.sychronizedList(new ArrayList<String>());
Or would the proper way to be
List referenceToList = Collections.synchronizedList(OtherClass.mainList);
Also is there any difference in the way i would iterate over the list, or is it the same as if All the adding and reading was contained in one Class?
It doesn't matter which class the list is contained in - the synchronization is for controlling access to reads and writes to that list from multiple threads (again, regardless of the class it's contained in). Once you've wrapped it in a call to Collections.synchronizedList, there's no point in doing it again.
For clarity (based on your question), your code would look like this:
class OtherClass {
public static List mainList = Collections.synchronizedList(new ArrayList());
}
class RandomClass {
public static List referenceToList = OtherClass.mainList;
}
Here, referenceToList is just a pointer to the same list that mainList points to, which has read/write access synchronized.
As a note, there are other List implementations that are designed for concurrent access situations, such as CopyOnWriteArrayList.
Collection col = new LinkedList();
Is there a way to call col.addFirst ?
Yes, if you cast to LinkedList:
((LinkedList) col).addFirst(..)
But this is discouraged, because you don't always know the concrete type of the collection. You can check with instanceof, but that is not good object oriented code. If you really require a LinkedList, require a LinkedList (rather than Collection)
If you declare a variable as Collection, this means that you normally plan to consider this variable, in the rest of your program, as a simple Collection, and not as a linked list. The methods offered by the Collection interface should be sufficient for the rest of your program using this variable.
If you need access to a specific method only present in the LinkedList class, then the variable should be a declared as LinkedList.
I am not sure why you need to use Collection in this case, however you can still "program to an interface and not to an implementation" if you use the interface java.util.Deque which, by chance, also extends java.util.Collection
Deque<String> deque = new LinkedList<String>();
deque.addFirst("Hello");
Collection<String> collection = deque;
If you use List instead of Collection, then the .add() method is available. Add at index 0 to put it in on the first position.
list.add(0, object)
I'm trying to write a method that takes in a List and create a new List of the same type based on it. That is, if the input list is an ArrayList, then I want the method to create a new ArrayList. The problem is that the program won't know if the List is an ArrayList or a LinkedList until runtime.
So far I've tried using the clone() method, but I don't think it works because the List class doesn't have clone() defined, and when I cast the input list as an Object and then clone then recast as a List, it also doesn't work (I'm not sure why).
All the standard lists from the JDK support clone, so
List copy = (List)((Cloneable)somelist).clone()
should work fine.
of course you can use reflection
Class c = somelist.getClass();
List newlist = (List)c.newInstance();
newlist.addAll(somelist);
Can you say more about why you want to do this? Without a good rationale, I'd contend:
Consider not doing this at all, but instead:
static <T> List<T> cloneMyList(final List<T> source)
{
return new ArrayList<T>(source);
}
If what you REALLY want is an efficient way to create a second copy of a known list, maybe the underlying implementation type really doesn't matter. In that case, just use an ArrayList which can be efficiently allocated using the List copy constructor.
Here it is:
List<YourType> destinationList = new ArrayList<>(sourceList.size());
Collections.copy(destinationList, sourceList);