I needed to create an arraylist without an element of another arraylist, but I need this new arraylist to keep updating. For example, an element of the old arraylist is removed, also remove in the new one.
But I did not want to remove the element of the two arraylist, only the old one, so as not to have much code
(My method "showPeople" is updated every 1 second)
My code:
ArrayList<Person> personList = new ArrayList<>();
private void method(){
personList.add(new People("Name"))
}
private void showPeople(){
ArrayList<Person> newPersonList =
new ArrayList<>(personList.stream()
.filter(person -> !person.getName().equals("Test"))
.collect(Collectors.toList()))
for (int i = 0; i < newPersonList.size(); i++){
gui.show(newPersonList.get(i).getName());
}
}
The problem is that when I create the new arraylist and remove an item from the old one, the new one does not update
You're making multiple copies of your list; instead, do something like:
List<Person> filterPeople(List<Person> people, #NotNull String name) {
return people.stream()
.filter(person -> !name.equals(person.getName()))
.collect(Collectors.toList());
}
If you're uncomfortable with the lack of guarantees on the the shape of the List, you can be explicit:
.collect(Collectors.toCollection(ArrayList::new));
It's still unclear what you're asking, however. I suggest you provide a minimal, complete, and verifiable example.
If you want the list without the element to keep updating, you can create a view of the list by extending AbstractList.
The API documentation contains instructions as to the methods you would need to override. If you don't want the list to be modifiable through the view, all you need to do is to override the get and size methods:
class ListView extends AbstractList<String> {
private final List<String> delegate; // Initialize in constructor.
public T get(int i) {
int pos = delegate.indexOf("Test");
if (pos < 0 || i < pos) return delegate.get(i);
return delegate.get(i + 1);
}
public int size() {
return delegate.size() - (delegate.contains("Test") ? 1 : 0);
}
}
This will repeatedly search for the "Test" element, because there is no way for the view to know if the delegate list has been updated underneath it.
Here's a handy method:
private static <T> List<T> CopyListWithoutItem(List<T> listToCopy, T itemToNotCopy) {
return listToCopy.stream().filter(item -> !item.equals(itemToNotCopy)).collect(Collectors.toList());
}
You can use that: List<String> elements = list.stream().distinct().collect(Collectors.toList());
That will remove duplicates.
I have an ArrayList of type RemoveTest, where RemoveTest is a user defined class.
RemoveTest has two properties of String type mId and rmId.
I need to find in the ArrayList, elements(Objects of type RemoveTest) satisfying the below criteria: such that the value of obj1.rmId() is same as obj2.getmId() and then remove both of these elements(obj1 and obj2).
I tried this by writing the below code:
import java.util.ArrayList;
import java.util.Iterator;
public class RemoveItr {
public static void main(String[] args){
ArrayList<RemoveTest> eleList = new ArrayList<RemoveTest>();
RemoveTest obj1 = new RemoveTest();
obj1.setmId("m1");
obj1.setRmId("");
RemoveTest obj2 = new RemoveTest();
obj2.setmId("m2");
obj2.setRmId("m1");
RemoveTest obj3 = new RemoveTest();
obj3.setmId("m3");
obj3.setRmId("");
RemoveTest obj4 = new RemoveTest();
obj4.setmId("m4");
obj4.setRmId("m3");
RemoveTest obj5 = new RemoveTest();
obj5.setmId("m5");
obj5.setRmId("");
eleList.add(obj1);
eleList.add(obj2);
eleList.add(obj3);
eleList.add(obj4);
eleList.add(obj5);
Iterator<RemoveTest> i = eleList.iterator();
while(i.hasNext()){
RemoveTest fwdM =(RemoveTest)i.next();
String fwdId = fwdM.getmId();
Iterator<RemoveTest> ni = eleList.iterator();
while(ni.hasNext()){
RemoveTest revM =(RemoveTest)ni.next();
String revId = revM.getRmId();
if(fwdId.equals(revId)){
System.out.println("fwdId "+fwdId+"- revId "+revId);
i.remove();
ni.remove();
}
}
}
}
}
public class RemoveTest {
String mId;
String rmId;
public String getmId() {
return mId;
}
public void setmId(String mId) {
this.mId = mId;
}
public String getRmId() {
return rmId;
}
public void setRmId(String rmId) {
this.rmId = rmId;
}
}
Note: both classes are Public as they were not in the same source file.
But, I got ConcurrentModificationException and I believe it is because, that as I was already in the middle of iterating through the arraylist, and then other loop(iterator) steps in and tries to operate on the same ArrayList.
Is this understanding correct? and If so, how can I resolve this problem and achieve the solution.
You can't modify a collection while iterating over it, except by using Iterator.remove().
This rule implies that you can't use two iterators simultaneously and expect remove() to work, because calling remove() on one iterator will violate the rule for the other iterator.
The solution is to collect all the entries that need deleting in a separate Set, then after your logic has completed, call List.removeAll(set).
Given this, you don't need iterators at all - just use the foreach syntax:
For a simplistic example:
List<RemoveTest> list = new ArrayList<RemoveTest>();
// populate list
Set<RemoveTest> removals = new HashSet<RemoveTest>();
for (RemoveTest i : list)
for (RemoveTest j : list)
if (...)
removals.add(i); // j will get added in another iteration
list.removeAll(removals);
Use CopyOnWriteArrayList instead of ArrayList, it should solve your problem.
I am trying to designing a software that convert a flowchart into java or any other code. However I repeatedly getting the ConcurrentModificationException..
But I can't use a boolean to prevent concurrentModification, because access to the linked list happens in various places.
So as a solution I created the below adapter class. However it also throws the same exception from next method. Are there any other solution or if can, plz let me know how to modify my codes...
thank you very much...
import java.util.Iterator;
import java.util.LinkedList;
public class LinkedListAdapter<T> extends LinkedList<T>{
#Override
public boolean add(T t){
boolean b;
synchronized(this){
b = super.add(t);
}
return b;
}
#Override
public T remove(){
T t;
synchronized(this){
t = super.remove();
}
return t;
}
#Override
public Iterator<T> iterator(){
final LinkedListAdapter<T> adap = this;
return
new Iterator<T>(){
private Iterator<T> iter;
{
synchronized(adap){
iter = LinkedListAdapter.this.getIterator();
}
}
#Override
public boolean hasNext() {
boolean b;
synchronized(adap){
b = iter.hasNext();
}
return b;
}
#Override
public T next() {
T t;
synchronized(adap){
t = iter.next();
}
return t;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
protected Iterator<T> getIterator() {
Iterator<T> iter;
synchronized(this){
iter = super.iterator();
}
return iter;
}
}
The ConcurrentModificationException is usually thrown when iterating through the list and in the same time usually another thread or even the same loop tries to modify (add / remove) the contents of the list.
Using a synchronizedList or a synchronized list still has to be synchronised externally when iterating over it.
If you use ConcurrentLinkedQueue you don't have these issues.
Queue<Task> tasks = new ConcurrentLinkedQueue<Task>();
tasks.add(task); // thread safe
tasks.remove(task2); // thread safe
for(Task t: tasks) // can iterate without a CME.
Note: if you are using a queue with another thread I suggest you use an ExecutorService as this combines a Queue with a ThreadPool and make working with "background" thread much easier.
why not use LinkedBlockingQueue? http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html
BTW, it's not neceserally have to do with synchronization. a code like this:
for(Value v : valuesList){
valueslist.add(new Value());
}
would cause this exception as well. check your code for possible modifications of the list when it's being iterated over.
This happens when you iterate over the list and add elements to it in the body of the loop. You can remove elements safely when you use the remove() method of the iterator but not by calling any of the remove() methods of the list itself.
The solution is to copy the list before you iterate over it:
List<T> copy = new ArrayList<T>( list );
for( T e : copy ) {
... you can now modify "list" safely ...
}
Java collections are fail-fast, that means that all existing Iterators become invalid the moment the underlying collection is modified - synchronizing the modification does not stop the list from invalidating all iterators.
As a workaround you can create a copy of the list to iterate over or postpone modifications until the iteration is finished. To remove entries you can also use the iterator.remove() method which keeps the iterator itself valid.
List<X> myList = ....
List<X> myThreadSafeList = synchronizedList(myList);
synchronizedList(myList)
Notice the following statement in the JavaDoc:
It is imperative that the user manually synchronize on the returned list when iterating over it:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
The answer here: Why am I getting java.util.ConcurrentModificationException? helped me a lot.
I will copy and paste it here in case anyone is looking to fix this error:
When you iterate through a list, you can't remove items from it. Doing so causes the exception.
Do:
int size = list.size();
for (int i = 0 ; i< size ; i++) {
list.add(0,"art");
list.remove(6);
System.out.println(list);
}
I have an ArrayList that I want to iterate over. While iterating over it I have to remove elements at the same time. Obviously this throws a java.util.ConcurrentModificationException.
What is the best practice to handle this problem? Should I clone the list first?
I remove the elements not in the loop itself but another part of the code.
My code looks like this:
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething might call Test.removeA();
Two options:
Create a list of values you wish to remove, adding to that list within the loop, then call originalList.removeAll(valuesToRemove) at the end
Use the remove() method on the iterator itself. Note that this means you can't use the enhanced for loop.
As an example of the second option, removing any strings with a length greater than 5 from a list:
List<String> list = new ArrayList<String>();
...
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String value = iterator.next();
if (value.length() > 5) {
iterator.remove();
}
}
From the JavaDocs of the ArrayList
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.
You are trying to remove value from list in advanced "for loop", which is not possible, even if you apply any trick (which you did in your code).
Better way is to code iterator level as other advised here.
I wonder how people have not suggested traditional for loop approach.
for( int i = 0; i < lStringList.size(); i++ )
{
String lValue = lStringList.get( i );
if(lValue.equals("_Not_Required"))
{
lStringList.remove(lValue);
i--;
}
}
This works as well.
In Java 8 you can use the Collection Interface and do this by calling the removeIf method:
yourList.removeIf((A a) -> a.value == 2);
More information can be found here
You should really just iterate back the array in the traditional way
Every time you remove an element from the list, the elements after will be push forward. As long as you don't change elements other than the iterating one, the following code should work.
public class Test(){
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff(){
for(int i = (abc.size() - 1); i >= 0; i--)
abc.get(i).doSomething();
}
public void removeA(A a){
abc.remove(a);
}
}
While iterating the list, if you want to remove the element is possible. Let see below my examples,
ArrayList<String> names = new ArrayList<String>();
names.add("abc");
names.add("def");
names.add("ghi");
names.add("xyz");
I have the above names of Array list. And i want to remove the "def" name from the above list,
for(String name : names){
if(name.equals("def")){
names.remove("def");
}
}
The above code throws the ConcurrentModificationException exception because you are modifying the list while iterating.
So, to remove the "def" name from Arraylist by doing this way,
Iterator<String> itr = names.iterator();
while(itr.hasNext()){
String name = itr.next();
if(name.equals("def")){
itr.remove();
}
}
The above code, through iterator we can remove the "def" name from the Arraylist and try to print the array, you would be see the below output.
Output : [abc, ghi, xyz]
Do the loop in the normal way, the java.util.ConcurrentModificationException is an error related to the elements that are accessed.
So try:
for(int i = 0; i < list.size(); i++){
lista.get(i).action();
}
Here is an example where I use a different list to add the objects for removal, then afterwards I use stream.foreach to remove elements from original list :
private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList();
...
private void removeOutdatedRowsElementsFromCustomerView()
{
ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime());
long diff;
long diffSeconds;
List<Object> objectsToRemove = new ArrayList<>();
for(CustomerTableEntry item: customersTableViewItems) {
diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime();
diffSeconds = diff / 1000 % 60;
if(diffSeconds > 10) {
// Element has been idle for too long, meaning no communication, hence remove it
System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName());
objectsToRemove.add(item);
}
}
objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o));
}
One option is to modify the removeA method to this -
public void removeA(A a,Iterator<A> iterator) {
iterator.remove(a);
}
But this would mean your doSomething() should be able to pass the iterator to the remove method. Not a very good idea.
Can you do this in two step approach :
In the first loop when you iterate over the list , instead of removing the selected elements , mark them as to be deleted. For this , you may simply copy these elements ( shallow copy ) into another List.
Then , once your iteration is done , simply do a removeAll from the first list all elements in the second list.
In my case, the accepted answer is not working, It stops Exception but it causes some inconsistency in my List. The following solution is perfectly working for me.
List<String> list = new ArrayList<>();
List<String> itemsToRemove = new ArrayList<>();
for (String value: list) {
if (value.length() > 5) { // your condition
itemsToRemove.add(value);
}
}
list.removeAll(itemsToRemove);
In this code, I have added the items to remove, in another list and then used list.removeAll method to remove all required items.
Instead of using For each loop, use normal for loop. for example,the below code removes all the element in the array list without giving java.util.ConcurrentModificationException. You can modify the condition in the loop according to your use case.
for(int i=0; i<abc.size(); i++) {
e.remove(i);
}
Sometimes old school is best. Just go for a simple for loop but make sure you start at the end of the list otherwise as you remove items you will get out of sync with your index.
List<String> list = new ArrayList<>();
for (int i = list.size() - 1; i >= 0; i--) {
if ("removeMe".equals(list.get(i))) {
list.remove(i);
}
}
You can also use CopyOnWriteArrayList instead of an ArrayList. This is the latest recommended approach by from JDK 1.5 onwards.
Do somehting simple like this:
for (Object object: (ArrayList<String>) list.clone()) {
list.remove(object);
}
An alternative Java 8 solution using stream:
theList = theList.stream()
.filter(element -> !shouldBeRemoved(element))
.collect(Collectors.toList());
In Java 7 you can use Guava instead:
theList = FluentIterable.from(theList)
.filter(new Predicate<String>() {
#Override
public boolean apply(String element) {
return !shouldBeRemoved(element);
}
})
.toImmutableList();
Note, that the Guava example results in an immutable list which may or may not be what you want.
for (A a : new ArrayList<>(abc)) {
a.doSomething();
abc.remove(a);
}
"Should I clone the list first?"
That will be the easiest solution, remove from the clone, and copy the clone back after removal.
An example from my rummikub game:
SuppressWarnings("unchecked")
public void removeStones() {
ArrayList<Stone> clone = (ArrayList<Stone>) stones.clone();
// remove the stones moved to the table
for (Stone stone : stones) {
if (stone.isOnTable()) {
clone.remove(stone);
}
}
stones = (ArrayList<Stone>) clone.clone();
sortStones();
}
I arrive late I know but I answer this because I think this solution is simple and elegant:
List<String> listFixed = new ArrayList<String>();
List<String> dynamicList = new ArrayList<String>();
public void fillingList() {
listFixed.add("Andrea");
listFixed.add("Susana");
listFixed.add("Oscar");
listFixed.add("Valeria");
listFixed.add("Kathy");
listFixed.add("Laura");
listFixed.add("Ana");
listFixed.add("Becker");
listFixed.add("Abraham");
dynamicList.addAll(listFixed);
}
public void updatingListFixed() {
for (String newList : dynamicList) {
if (!listFixed.contains(newList)) {
listFixed.add(newList);
}
}
//this is for add elements if you want eraser also
String removeRegister="";
for (String fixedList : listFixed) {
if (!dynamicList.contains(fixedList)) {
removeResgister = fixedList;
}
}
fixedList.remove(removeRegister);
}
All this is for updating from one list to other and you can make all from just one list
and in method updating you check both list and can eraser or add elements betwen list.
This means both list always it same size
Use Iterator instead of Array List
Have a set be converted to iterator with type match
And move to the next element and remove
Iterator<Insured> itr = insuredSet.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
Moving to the next is important here as it should take the index to remove element.
List<String> list1 = new ArrayList<>();
list1.addAll(OriginalList);
List<String> list2 = new ArrayList<>();
list2.addAll(OriginalList);
This is also an option.
If your goal is to remove all elements from the list, you can iterate over each item, and then call:
list.clear()
What about of
import java.util.Collections;
List<A> abc = Collections.synchronizedList(new ArrayList<>());
ERROR
There was a mistake when I added to the same list from where I took elements:
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
for (i in this) {
this.add(_fun(i)) <--- ERROR
}
return this <--- ERROR
}
DECISION
Works great when adding to a new list:
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
val newList = mutableListOf<T>() <--- DECISION
for (i in this) {
newList.add(_fun(i)) <--- DECISION
}
return newList <--- DECISION
}
Just add a break after your ArrayList.remove(A) statement
Okay, so I'm supposed to implement a set that contains elements of type Object with no duplicates which means that I need to compare each new element with the previous elements in the set. The set has its own class and has a method for inserting a new element.
My question is: How do I use the iterator I wrote below to compare all the entries in the set with the proposed element to add?
class SetIterator implements MyIterator {
private ArraySet arr; //ArraySet is the name of the Set class
private int n;
SetIterator(ArraySet myArraySet)
{
arr = myArraySet;
n = 0;
}
#Override
public boolean hasNext()
{
return (n <= arr.size());
}
#Override
public Object next()
{
if (hasNext())
return arr[n++];
}
}
Thanks!
You'd need something like this in ArraySet.java.
public Iterator iterator()
{
return new SetIterator(this);
}
public boolean add(Object o)
{
for (Object item : this)
if (o.equals(next)) return false;
}
// add code to put o in the array
return true;
}
The for loop is translated by the compiler to something like this:
Iterator it = this.iterator();
while (it.hasNext())
{
Object item = it.next();
if (o.equals(next)) return false;
}
The implementation of Set should guarantee no-duplication rather than the Iterator.
That is, your Set.add() and its constructor with Collection as argument should guarantee no-duplication.
The Iterator just implements hasNext(), next(), and remove().
If Iterator takes care of duplication checking, your Set will violate java.util.Set contract. Moreover, the Iterator will take two responsibilities—checking duplication and traversing, that violates “Single Responsibily Principle”.
Yes, I just want an example on how to use that iterator instead of a for loop or a while loop.
You pretty much have to use some kind of loop to use a Iterator. Here is the basic pattern:
Iterator it = ... // instantiate the iterator
while (it.hasNext()) {
Object obj = it.next();
... // do something with obj
}
If the collection object (e.g. your set of objects) implements Iterable then you can use the new for loop syntax; e.g.
for (Object obj : yourSet) {
... // do something with obj
}
Of course, there are other ways to express this, but they all involve (somewhere) a loop of some kind to pull the objects from the iterator.