Iterating through collections to add items but throwing ConcurrentModificationException - java

package com.ripal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public class Outputs {
public void show() {
final ArrayList<String> list = new ArrayList<String>();
list.add("banana");
list.add("apple");
Iterator<String> itr = list.iterator();
Collections.sort(list);
while (itr.hasNext()) {
System.out.println(itr.next() + " ");
}
}
}
class Test {
public static void main(String[] args) {
Outputs outputs = new Outputs();
outputs.show();
}
}

ArrayList has a fail fast iterator. You can modify the collection only via the iterator. Any other modification done outside is detected sooner after calling the iterator methods and a ConcurrentModificationException is thrown. In your case after creating the iterator you sort the array in place and that sorting routine modifies the contents of the array, leading to ConcurrentModificationException upon using the iterator. To fix the issue, just perform the sorting before you create the iterator. Here's how it looks.
Collections.sort(list);
Iterator<String> itr = list.iterator();

Related

How can we handle the Java ConcurrentModificationException using try-catch?

I am trying to handle the java ConcurrentModificationException exception using try-catch block but still I am getting the same error when compiling the code.
import java.util.*;
public class failFast{
public static void main(String[] args){
Map<Integer,String> map = new HashMap<>();
map.put(100,"Melani");
map.put(101,"Harshika");
map.put(102,"Nimna");
Iterator itr = map.keySet().iterator();
while(itr.hasNext()){
System.out.println(itr.next());
try{
map.put(103,"Nirmani");
}
catch(Exception e){
System.out.println("Exception is thrown "+e);
}
}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(Unknown Source)
at java.util.HashMap$KeyIterator.next(Unknown Source)
at failFast.main(failFast.java:12)
I don't now exactly what you are trying to achive (your code doesn't make much sense for me). Basically you can't change a Map or an other Collection while iterating over it. The only way to change the underlying structure is with the actual Iterator but this is very limited. To catch the ConcurrentModificationException makes not much sense because with your code it will always be thrown, so the catch-block would be your normal code flow, which is really not good.
Possibility 1: Copy keySet to an other collection and iterate over this one
import java.util.*;
public class FailFast{
public static void main(String[] args){
Map<Integer,String> map = new HashMap<>();
map.put(100,"Melani");
map.put(101,"Harshika");
map.put(102,"Nimna");
// Copy keySet to an other collection and iterate over this one
Iterator itr = new ArrayList(map.keySet()).iterator();
while(itr.hasNext()){
System.out.println(itr.next());
map.put(103,"Nirmani");
}
Possibility 2: Collect all the changes and apply them after the loop (this is what I would do)
import java.util.*;
public class FailFast{
public static void main(String[] args){
Map<Integer,String> map = new HashMap<>();
map.put(100,"Melani");
map.put(101,"Harshika");
map.put(102,"Nimna");
Iterator itr = map.keySet().iterator();
Map<Integer,String> changes = new HashMap<>();
while(itr.hasNext()){
System.out.println(itr.next());
changes.put(103,"Nirmani");
}
map.putAll(changes);

Concurrent Modification Exception while adding elements to ArrayList recursively

Getting Concurrent Modification Exception while adding elements to ArrayList recursively.
import java.util.*;
public class Hello {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String str = sc.next();
System.out.println(gss(str));
}
public static ArrayList<String> gss(String str) {
if(str.length() == 0){
ArrayList<String> list = new ArrayList<String>();
list.add("");
return list;
}
ArrayList<String> list = gss(str.substring(1));
for(String temp : list){
list.add(str.charAt(0)+temp); // Problem
}
return list;
}
}
Solution: To just form new ArrayList at each call stack and return it.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
String str = sc.next();
System.out.println(gss(str));
}
public static ArrayList<String> gss(String str) {
if(str.length() == 0){
ArrayList<String> list = new ArrayList<String>();
list.add("");
return list;
}
ArrayList<String> list = gss(str.substring(1));
ArrayList<String> listToReturn = new ArrayList<>();
for(String temp : list){
listToReturn.add(temp);
}
for(String temp : list){
listToReturn.add(str.charAt(0) + temp);
}
return listToReturn;
}
}
I have recently come across this blog.
Which says, It uses a transient variable called modCount, which keeps track of how many times a list is modified structurally. Structural modifications are those that change the size of the list, which may affect the progress of iteration and may yield incorrect results. Both Iterator and ListIterator uses this field to detect unexpected change. Other methods of List which structurally modify List also uses this method e.g. add(), remove().
Cause: The real cause of ConcurrentModficationException is inconsistent modCount. When you are iterating over ArrayList then Iterator's next() method keep track of modCount. If you modify the collection by adding or removing element then modCount will change and it will not match with the expected modCount, hence Iterator will throw ConcurrentModificationException.

Can I use listiterator in Java to access elements in random positions?

I'm writing code that goes through article records (in database). I load the database in memory and store it in ListIterator.
Does anyone know if I can access elements in random positions?
I created this Java example:
package com.myjava.listiterator;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class MyListIterator {
public static void main(String a[]){
List<Integer> li = new ArrayList<Integer>();
ListIterator<Integer> litr = null;
li.add(23);
li.add(98);
li.add(29);
li.add(71);
li.add(5);
litr=li.listIterator();
System.out.println("Elements in forward directiton");
while(litr.hasNext()){
System.out.println(litr.next());
}
System.out.println("Elements in backward directiton");
while(litr.hasPrevious()){
System.out.println(litr.previous());
}
// How to access litr[3]?
}
}
This code loops through numbers forward and backward. See my last comment. Can I access litr[3]?
// How to access litr[3]?
No you can't get randomly from an iterator.
From ListIterator docs
A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next().
// How to access litr[3]?
I can see a possibility here by getting it from list directly li.get(3);
If you don't have a list in hand and only have iterater, first prepare a list
List<ObjectType> dupList= new ArrayList<ObjectType>();
while (itr.hasNext())
dupList.add(itr.next());
Alternative if you have to get only one object:
ObjectType target =null;
int i = 0;
while(itr.hasNext() && i!=3){
i++;
target = itr.next();
}
//access fourth element via target variable.
Now pass a random index to this list (dupList)
Your list instance is an ArryaList, simply use it directly.
package com.myjava.listiterator;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class MyListIterator {
public static void main(String a[]){
ArrayList<Integer> li = new ArrayList<Integer>();
li.add(23);
li.add(98);
li.add(29);
li.add(71);
li.add(5);
....
// How to access litr[3]?
System.out.println(li.get(3));
}
}
If your method only accept ListIterator and cannot be modified.
Here is a solution if you are not concerned about performance.
package com.myjava.listiterator;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class MyListIterator {
public void someMethodOnlyAcceptListIterator(ListIterator<Integer> iterator){
List<Integer> tmpList = new ArrayList<Integer>();
// Save all items to the tmpList
while(iterator.hasNext()){
tmpList.add(litr.next());
}
// Access item
System.out.println(tmpList.get(3));
}
}
There is no such functionality in ListIterator. ListIteratorallows for forward and backward iterations.
As for your solution to get litr[3], you can take your ListIteratorand apply all its elements into an ArrayList and do list.get(3).
you can directly use like this li.get(3)
you can also do like this but not good.
while(litr.hasNext()){
int curentIndex = litr.nextIndex()-1;
if(ranIndex > currentIndex) {
while(litr.hasNext()){
if(ranIndex == litr.nextIndex()-1)
sysout(yourrandomindex);
after that reset back the list curentIndex
}
}
// less than code here
}

java.util.ConcurrentModificationException while removing items from collection [duplicate]

This question already has answers here:
List.remove strange behaviour
(4 answers)
Closed 7 years ago.
I am learning Java's Collection framework. I wrote this little program to check why we can't use For-each to remove elements.
Code:
import java.util.ArrayList;
class intro{
public static void main(String args[]){
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
for(String name:names){
names.remove(name);
}
for(String name:names){
System.out.println(name);
}
}
}
Outputs:
Saxena
And
import java.util.ArrayList;
class intro{
public static void main(String args[]){
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
names.add("Arvind");
for(String name:names){
names.remove(name);
}
for(String name:names){
System.out.println(name);
}
}
}
Throws:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at intro.main(intro.java:15)
How come just the addition of one more element to collection is causing the error?
Normally when you remove an element from a collection while looping over the collection, you'll get a ConcurrentModificationException. This is partially why the Iterator interface has a remove() method. Using an iterator is the only safe way to modify a collection of elements while traversing them.
The code would go something like this:
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
names.add("Arvind");
for (Iterator<String> iterator = name.iterator(); iterator.hasNext();) {
String string = iterator.next();
if (string.isEmpty()) {
iterator.remove();
}
}

java- reset list iterator to first element of the list

I need to know how to "reset" LinkedList iterator to its first element.
For example:
LinkedList<String> list;
Iterator iter=list.listIterator;
iter.next();
iter.next();
Over and over again and after many moves of the iterator, I need to "reset" the position of the iterator.
I want to ask how I can "reset" my iterator to the first element.
I know that I can get list iterator of the first element in this way:
iter= list.listIterator(1);
Is this the best solution? Or maybe I missed something in Oracle docs?
You can call listIterator method again to get an instance of iterator pointing at beginning of list:
iter = list.listIterator();
Best would be not using LinkedList at all, usually it is slower in all disciplines, and less handy. (When mainly inserting/deleting to the front, especially for big arrays LinkedList is faster)
Use ArrayList, and iterate with
int len = list.size();
for (int i = 0; i < len; i++) {
Element ele = list.get(i);
}
Reset is trivial, just loop again.
If you insist on using an iterator, then you have to use a new iterator:
iter = list.listIterator();
(I saw only once in my life an advantage of LinkedList: i could loop through whith a while loop and remove the first element)
This is an alternative solution, but one could argue it doesn't add enough value to make it worth it:
import com.google.common.collect.Iterables;
...
Iterator<String> iter = Iterables.cycle(list).iterator();
if(iter.hasNext()) {
str = iter.next();
}
Calling hasNext() will reset the iterator cursor to the beginning if it's a the end.
What you may actually want to use is an Iterable that can return a fresh Iterator multiple times by calling iterator().
//A function that needs to iterate multiple times can be given one Iterable:
public void func(Iterable<Type> ible) {
Iterator<Type> it = ible.iterator(); //Gets an iterator
while (it.hasNext()) {
it.next();
}
it = ible.iterator(); //Gets a NEW iterator, also from the beginning
while (it.hasNext()) {
it.next();
}
}
You must define what the iterator() method does just once beforehand:
void main() {
LinkedList<String> list; //This could be any type of object that has an iterator
//Define an Iterable that knows how to retrieve a fresh iterator
Iterable<Type> ible = new Iterable<Type>() {
#Override
public Iterator<Type> iterator() {
return list.listIterator(); //Define how to get a fresh iterator from any object
}
};
//Now with a single instance of an Iterable,
func(ible); //you can iterate through it multiple times.
}
If the order doesn't matter, we can re-iterate backward with the same iterator using the hasPrevious() and previous() methods:
ListIterator<T> lit = myList.listIterator(); // create just one iterator
Initially the iterator sits at the beginning, we do forward iteration:
while (lit.hasNext()) process(lit.next()); // begin -> end
Then the iterator sits at the end, we can do backward iteration:
while (lit.hasPrevious()) process2(lit.previous()); // end -> begin
Calling iterator() on a Collection impl, probably would get a new Iterator on each call.
Thus, you can simply call iterator() again to get a new one.
Code
IteratorLearn.java
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
/**
* Iterator learn.
*
* #author eric
* #date 12/30/18 4:03 PM
*/
public class IteratorLearn {
#Test
public void test() {
Collection<Integer> c = new HashSet<>();
for (int i = 0; i < 10; i++) {
c.add(i);
}
Iterator it;
// iterate,
it = c.iterator();
System.out.println("\niterate:");
while (it.hasNext()) {
System.out.printf("\t%d\n", it.next());
}
Assert.assertFalse(it.hasNext());
// consume,
it = c.iterator();
System.out.println("\nconsume elements:");
it.forEachRemaining(ele -> System.out.printf("\t%d\n", ele));
Assert.assertFalse(it.hasNext());
}
}
Output:
iterate:
0
1
2
3
4
5
6
7
8
9
consume elements:
0
1
2
3
4
5
6
7
8
9
What you can do is, set the iterator to the first position mannualy with a while loop.
while(iter.hasPrevious())
{
iter.previous();
}
when you get out of the loop you will have your iterator at the position 0
sorry any grammar mistakes
Well some of the version of java does not have a reset method for the iterator, so we are required to use the multiple iterator for number of use cases, which ultimately increases the memory consumption.
so it's simple way to use the same iterator again if needed by declaring a global function and pass the collection as argument.
for eg.
enter image description here
for eg (Written program)
package com.javalearn;
import java.util.ArrayList;
import java.util.Iterator;
public class Java_Learn {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("It's");
list.add("me.");
iter(list);
System.out.println(list.size());
System.out.println(list.indexOf("me."));
System.out.println(list.remove(3));
iter(list);
}
static void iter(ArrayList<String> arr){
Iterator itr = arr.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}

Categories