i have an arraylist and i want to add and remove many items at he same(almost) time. So i decide to create 2 methods. In the first method i implement the method which contains the remove part i use something like:
//my list
ArrayList<Human> list= new ArrayList<Human>(100);
//Human is the object of the class Human
List<Human> syncList = Collections.synchronizedList(new ArrayList<Human>());
synchronized (syncList){
for (Iterator<Human> iter = list.iterator(); iter.hasNext();) {
Human = iter.next();
-
-
//using the removes method of the iterator
it.removes(something);
And in the second method (which i need to add many items) something like this:
for( ListIterator<Human> it = list.listIterator();it.hasNext();){
List<Human> syncList = Collections.synchronizedList(newArrayList<Human>());
synchronized (syncList){
-
-
//using the add method of the iterator list
it.add(something)
Now i realize that when those two void methods finished and the list called by another function don't have the appropriate behaviour. I mean that some of the elements didn't add or removed from the list. How can i fix this?any ideas?
you are synchronizing on 2 entirely different objects, hence the inconsistent behavior. your call to synchronizedList() is returning a wrapper around the original list, on which you are synchronizing. since the 2 methods are using different wrappers, no actual synchronization is happening. you just need to synchronize on the original list implementation. of course, any other usage of the list member should also be synchronized.
Related
This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 8 years ago.
In Java, is it legal to call remove on a collection when iterating through the collection using a foreach loop? For instance:
List<String> names = ....
for (String name : names) {
// Do something
names.remove(name).
}
As an addendum, is it legal to remove items that have not been iterated over yet? For instance,
//Assume that the names list as duplicate entries
List<String> names = ....
for (String name : names) {
// Do something
while (names.remove(name));
}
To safely remove from a collection while iterating over it you should use an Iterator.
For example:
List<String> names = ....
Iterator<String> i = names.iterator();
while (i.hasNext()) {
String s = i.next(); // must be called before you can call i.remove()
// Do something
i.remove();
}
From the Java Documentation :
The iterators returned by this class's iterator and listIterator
methods are fail-fast: if the list is structurally modified at any
time after the iterator is created, in any way except through the
iterator's own remove or add methods, the iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future.
Perhaps what is unclear to many novices is the fact that iterating over a list using the for/foreach constructs implicitly creates an iterator which is necessarily inaccessible. This info can be found here
You don't want to do that. It can cause undefined behavior depending on the collection. You want to use an Iterator directly. Although the for each construct is syntactic sugar and is really using an iterator, it hides it from your code so you can't access it to call Iterator.remove.
The behavior of an iterator is
unspecified if the underlying
collection is modified while the
iteration is in progress in any way
other than by calling this method.
Instead write your code:
List<String> names = ....
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String name = it.next();
// Do something
it.remove();
}
Note that the code calls Iterator.remove, not List.remove.
Addendum:
Even if you are removing an element that has not been iterated over yet, you still don't want to modify the collection and then use the Iterator. It might modify the collection in a way that is surprising and affects future operations on the Iterator.
for (String name : new ArrayList<String>(names)) {
// Do something
names.remove(nameToRemove);
}
You clone the list names and iterate through the clone while you remove from the original list. A bit cleaner than the top answer.
The java design of the "enhanced for loop" was to not expose the iterator to code, but the only way to safely remove an item is to access the iterator. So in this case you have to do it old school:
for(Iterator<String> i = names.iterator(); i.hasNext();) {
String name = i.next();
//Do Something
i.remove();
}
If in the real code the enhanced for loop is really worth it, then you could add the items to a temporary collection and call removeAll on the list after the loop.
EDIT (re addendum): No, changing the list in any way outside the iterator.remove() method while iterating will cause problems. The only way around this is to use a CopyOnWriteArrayList, but that is really intended for concurrency issues.
The cheapest (in terms of lines of code) way to remove duplicates is to dump the list into a LinkedHashSet (and then back into a List if you need). This preserves insertion order while removing duplicates.
I didn't know about iterators, however here's what I was doing until today to remove elements from a list inside a loop:
List<String> names = ....
for (i=names.size()-1;i>=0;i--) {
// Do something
names.remove(i);
}
This is always working, and could be used in other languages or structs not supporting iterators.
Yes you can use the for-each loop,
To do that you have to maintain a separate list to hold removing items and then remove that list from names list using removeAll() method,
List<String> names = ....
// introduce a separate list to hold removing items
List<String> toRemove= new ArrayList<String>();
for (String name : names) {
// Do something: perform conditional checks
toRemove.add(name);
}
names.removeAll(toRemove);
// now names list holds expected values
Make sure this is not code smell. Is it possible to reverse the logic and be 'inclusive' rather than 'exclusive'?
List<String> names = ....
List<String> reducedNames = ....
for (String name : names) {
// Do something
if (conditionToIncludeMet)
reducedNames.add(name);
}
return reducedNames;
The situation that led me to this page involved old code that looped through a List using indecies to remove elements from the List. I wanted to refactor it to use the foreach style.
It looped through an entire list of elements to verify which ones the user had permission to access, and removed the ones that didn't have permission from the list.
List<Service> services = ...
for (int i=0; i<services.size(); i++) {
if (!isServicePermitted(user, services.get(i)))
services.remove(i);
}
To reverse this and not use the remove:
List<Service> services = ...
List<Service> permittedServices = ...
for (Service service:services) {
if (isServicePermitted(user, service))
permittedServices.add(service);
}
return permittedServices;
When would "remove" be preferred? One consideration is if gien a large list or expensive "add", combined with only a few removed compared to the list size. It might be more efficient to only do a few removes rather than a great many adds. But in my case the situation did not merit such an optimization.
Those saying that you can't safely remove an item from a collection except through the Iterator aren't quite correct, you can do it safely using one of the concurrent collections such as ConcurrentHashMap.
Try this 2. and change the condition to "WINTER" and you will wonder:
public static void main(String[] args) {
Season.add("Frühling");
Season.add("Sommer");
Season.add("Herbst");
Season.add("WINTER");
for (String s : Season) {
if(!s.equals("Sommer")) {
System.out.println(s);
continue;
}
Season.remove("Frühling");
}
}
It's better to use an Iterator when you want to remove element from a list
because the source code of remove is
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
so ,if you remove an element from the list, the list will be restructure ,the other element's index will be changed, this can result something that you want to happened.
Use
.remove() of Interator or
Use
CopyOnWriteArrayList
This question already has answers here:
What does it mean to "program to an interface"?
(33 answers)
Closed 6 years ago.
If we consider two implementations below, what's the actual use of the first one?
List<String> a= new ArrayList<String>();
ArrayList<String> b= new ArrayList<String>();
From what I have read in the posts, the first implementation helps in avoiding breaking change like we can change the implementation again as
a=new TreeList<String>();
But I don't understand whats the actual use of changing the implementation with treelist as we can use only the List interface methods?
But I don't understand whats the actual use of changing the implementation with treelist as we can use only the List interface methods?
Different implementations of interface List have different performance characteristics for different operations. Which implementation of List you should choose is not arbitrary - different implementations are more efficient for different purposes.
For example, inserting an element somewhere in the middle is expensive on an ArrayList, but cheap on a LinkedList, because of the way the implementations work. Likewise, accessing an element by index is cheap on an ArrayList, but expensive on a LinkedList.
It may happen that when you started writing your program, you used an ArrayList without thinking about it too much, but later you discover that a LinkedList would be more efficient.
When you've programmed against the interface List instead of a specific implementation, it's very easy to change from ArrayList to LinkedList - to the rest of the program, it still looks like a List, so you'd only have to change one line.
Lets say that you have decided to develop a more efficient List implementation of your own. Perhaps one that has better memory management internally, or may be a faster set method (insertion) implementation. You can just implement the List interface and rest of your code will continue to work without any change, except this one line. You can also extend ArrayList and write your own code.
//Old code
List<String> a = new ArrayList<String>();
a.set(0, "Test");
//New code
List<String> a = new MyCustomisedList<String>();
//Same code, but your optimized set logic. May be faster...
a.set(0, "Test");
A TreeList doesn't exist, so lets use a PersistentList as an example.
Lets say you have an #Entity that you want to save to a database:
public class MyMagicEntity {
#OneToMany
List<MyChildEntity> children;
public void setChildren(final List<MyChildEntity> children) {
this.children = children;
}
}
Now, when you create MyMagicEntity then you would do something like
final MyMagicEntity mme = new MyMagicEntity();
final List<MyChildEntity> children = new ArrayList<>();
children.add(new MyChildEntity("one"));
children.add(new MyChildEntity("two"));
children.add(new MyChildEntity("three"));
mme.setChildren(children);
//save to DB
So you created an ArrayList that you passed into your MyMagicEntity, which assigns it to the List - it doesn't care that the underlying implementation is as long as it's a List.
Now, later you do:
final MyMagicEntity mme = //load from DB
final List<Children> children = mme.getChildren();
So, what is children? Well, if we are using JPA and Hibernate it is actually a PersistentList, not an ArrayList.
As we access the members of children, Hibernate will go and pull them from the database. This List is still a List - your program doesn't have to know any of this.
Could you do this without using the List interface? No! Because:
you cannot create a PersistentList
Hibernate cannot create an ArrayList
Whilst this is an extreme example, where the underlying behaviour of the List is completely different, this applies in all sorts of other situations.
For example:
ArrayList and LinkedList have different performance characteristics, you may want to switch
Guava has an ImmutableList which you may want to use
Collections.unmodifyableList also implements List, which you may want to use
You could conceivably have a List backed by a file
The basic idea is that List defines what any list must be able to do, but not how it is done.
Here List is an Interface which contains all common operation method can perform with an List.
List Interface is parent for ArrayList , LinkedList and many more class. So, It can hold all these type of Object reference.
All these List method have different (or own type) Implementation with different class. So, whatever method you use will automatically apply according to override method definition of Object belong to the class.
List<String> a= new ArrayList<String>();
ArrayList<String> b= new ArrayList<String>();
Now , In Your case you can declare both ways is alright. but suppose a Scenario like this.
You are calling some services and you know that return any List Type (not specific) of Object. It may be a LinkedList or ArrayList or any other type of List.
at that time whatever response you get You can easily hold those responses in a List Type of Reference Variable.
and after gathering the result you can differentiate further of Object Type.
I have a question. I think i know the answer but for some reason i prefer to ask for it here.
So here is the scenario:
I have an Object which has a list as a field. Then i have a method that returns the list as an unmodifiableList.
The Oject class has other methods that add elements to the list.
So lets imagine a case where one thread is iterating throught the unmodifiable list and another thread that is adding elements to the list using the Object class method.
How do i make this thread safe? If i synchronize the unmodifiableList and the list itselft will it make it thread safe? After all they are two different object where the unmodifiableList has a field which is the naked list itselft.
You need to make the "naked" list synchronized:
private List<Foo> list = Collections.synchronizedList(new ArrayList<Foo>());
But beware: that will only make sure the list internal state is coherent. As soon as you iterate on the list, you can't prevent a modification to the list to happen between two calls to the list iterator. So nothing will prevent a ConcurrentModificationException to happen in that case. To prevent that, you should not return any reference (even an indirect one) to the list. All modifications and iterations to the list should be encapsulated in your class, and properly synchronized.
You can return an unmodifiable-clone of original list to the caller.
The disadvantage is that the caller may end up with a "stale" version of the list. However, by this way you achieve safe iterations. In concurrent world, it is OK to return last successfully updated data to the caller.
public List<Thing> getThings() {
List<Thing> copytOfThings = new ArrayList<>();
copyOfThings.addAll(_things); //original list items.
return Collections.unmodifiableList(copyOfThings);
}
There are a couple of ways you could do this:
Return a copy of the list, rather than an unmodifiable view of it
Rather than using the iterator, use List.get(int)
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.
What is Iterator and collections?
Does these two have any relations?
// the interface definition
Interface Iterator {
boolean hasNext();
Object next(); // note "one-way" traffic
void remove();
}
// an example
public static void main (String[] args){
ArrayList cars = new ArrayList();
for (int i = 0; i < 12; i++)
cars.add (new Car());
Iterator it = cats.iterator();
while (it.hasNext())
System.out.println ((Car)it.next());
}
Does the Interface Iterator has these method names alone predefined or its user defined?.
What does these four lines below actually tell?
cars.add (new Car());
Iterator it = cats.iterator();
while (it.hasNext())
System.out.println ((Car)it.next());
Thanks. I am going through a book in collections.
The Java collections are, as the name says, collections of things. If you don't know that word, look it up in a dictionary.
There are many types of collections. Take for example the mathematical concept of a set. You can put arbitrary things in a set, but it will never contain the same thing more than once. The things in the set are not ordered, that is you cannot say A comes before B. Another type of collection is a list. A list can contain the same thing more than once, and the order of the things in the list is important.
What all these collections have in common is that they contain things, which in Java are called elements. When you want to know which things are in a certain collection, you iterate over the collection, which is just another term for going through all elements. This is what an Iterator does. It basically starts at the beginning of a collection, you can always ask whether there is a next element (hasNext()), and if there is, you can get access to that element (next()), until you have iterated over all elements in the collection.
Technically iterators and collections are not directly related. However Iterators are mostly used together with collections to interate over the objects contained in the collection.
Iterators are a general and flexible concept that allows to interate objects without depending on the exact implementation of the entity that they iterate over.
An iterator is most commonly used as a mechanism for going through the elements of a collection.
The concept is not specific to Java at all, though the specific interface definition you show is.
See the Wikipedia article on Iterator for some discussion of what it means and how it's done in assorted languages including Java.
In Java, it is an Interface, so you can indeed implement your own, but sensible ones are defined for the collections in Java's collections library and for any Java Collection implementation the method
collection.iterator()
should return an iterator that will traverse the elements of that collection.
Also see the javadoc for Collection and Iterator for more.