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);
Related
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();
I was reading about concurrent modification exception and noticed in case of element removal using enhanced for loop throws concurrent modification exception whereas normal for loop doesn't.
Can someone please help me understand why this is happening, below code
import java.util.ArrayList;
import java.util.List;
public class ConcurrentModificationExceptionExample {
public static void main(String args[]) {
List<String> myList = new ArrayList<String>();
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("4");
myList.add("5");
// enhanced for loop
/* for(String s:myList){
if(s.equals("1")){
myList.remove("1");
}
}*/
// normal for loop
for(int i = 0; i<myList.size(); i++){
if(myList.get(i).equals("1")){
myList.remove("1");
}
}
System.out.println(myList);
}
}
for testing //enhanced for loop can be uncommented
This is because in your "normal for loop" code no Iterator is involved. Instead, you access the elements individually with get.
The loop notation
for (String s: myList) {
...
}
creates an iterator object behind the scenes. The iterator keeps track of collection modifications. When you make a modification without using the iterator you will get a ConcurrentModificationException.
When using
for (int i = 0; i < myList.size(); i++) {
...
}
and accessing the collection with
myList.get(i)
there is no iterator created, and therefore no chance for the exception to be thrown.
Enumeration is Fail-safe. Fail-safe iterators will work on the cloning of the original collection. then why it is throwing concurrentModificationException? please clarify.
Please find my code:
public static void main(String[] args) {
Vector<String> v=new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration en=(Enumeration) Collections.enumeration(v);
while(en.hasMoreElements())
{
String value=(String) en.nextElement();
System.out.println(value);
v.remove(value);//modifying the collection
}
}
Find the error message below
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.Vector$Itr.checkForComodification(Unknown Source)
at java.util.Vector$Itr.next(Unknown Source)
at java.util.Collections$2.nextElement(Unknown Source)
at valar.org.src.EnumerationTest.main(EnumerationTest.java:24)
Collections.enumeration(Collection) will create an iterator from the collection passed as parameter :
public static <T> Enumeration<T> enumeration(final Collection<T> c) {
return new Enumeration<T>() {
private final Iterator<T> i = c.iterator();
public boolean hasMoreElements() {
return i.hasNext();
}
public T nextElement() {
return i.next();
}
};
}
It means that the iterator is backed to the collection which you remove element in the iterator loop and you cannot remove an element of the collection on which you iterate with the iterator.
You should create a copy of the Vector you pass in the enumeration() invocation :
Enumeration<String> en = Collections.enumeration(new Vector<String>(v));
And as a side note, you should favor List interface and ArrayList implementation over Vector (that is synchronized) and declare generics collection that spares cast and increase the type safety of the code.
So it would give this code (I left the Vector use as it is maybe a not modifiable constraint but I specified the generics as it is often simpler to add even in a legacy code):
Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Enumeration<String> en = Collections.enumeration(new Vector<String>(v));
while (en.hasMoreElements()) {
String value = (String) en.nextElement();
System.out.println(value);
v.remove(value);// modifying the collection
}
Your Enumeration uses an Iterator internally. While iterating over the elements, you can't use the vector itself to remove items. You have to use the iterator. But you don't have access to it. Create an iterator instead:
public static void main(String[] args) {
final Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
// Use an Iterator to remove the value you are iterating over
final Iterator<String> iterator = v.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
System.out.println(value);
iterator.remove();
}
}
Though Vector is practically deprecated anyways. You should propably use a List instead:
The imports for the correct Lists (don't use the awt.List for this):
import java.util.ArrayList;
import java.util.List;
The changed code:
public static void main(String[] args) {
final List<String> v = new ArrayList<>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
final Iterator<String> iterator = v.iterator();
while (iterator.hasNext()) {
final String value = iterator.next();
System.out.println(value);
iterator.remove();
}
}
Also note you can use the interface as Type which is generally preferred to using the implementation.
Edit:
Looking at your example, maybe what you really need is a queue:
public static void main(String[] args) {
final Queue<String> v = new LinkedList<>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
System.out.println("Size: " + v.size());
for (String element = v.poll(); element != null; element = v.poll()) {
System.out.println(element);
}
System.out.println("Size: " + v.size());
}
Output:
Size: 3
Amit
Raj
Pathak
Size: 0
This works the same as your example. For more info on Collections see The official Collections Java Trail
Enumeration is Fail-safe.
Correct. (Allowing for some language difficulties.)
Fail-safe iterators will work on the cloning of the original collection.
Correct. (Allowing for some language difficulties.)
then why it is throwing concurrentModificationException?
Because there is no cloning involved.
Where is the cloning?
You are using Enumeration which is not supported removed method.Once you created a Enumeration then it test for checkForComodification .so when you do the remove from vector the modCount increases and expectedModCount not modified.
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
please modify your code using iterator
public static void main(String[] args) {
Vector<String> v = new Vector<String>();
v.add("Amit");
v.add("Raj");
v.add("Pathak");
v.add("Sumit");
v.add("Aron");
v.add("Trek");
Iterator<String> it =v.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
it.remove();
}
}
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();
}
}
How to remove duplicate elements in an array using HashMap without using hashset in java...Below code describes removal of duplicates in array..
Now i need to write using hashmap for generating key and value pairs
import java.util.*;
class TestArray{
public static void main(String arg[])
{
ArrayList<String> wordDulicate = new ArrayList<String>();
wordDulicate.add("chennai");
wordDulicate.add("bangalore");
wordDulicate.add("hyderabad");
wordDulicate.add("delhi");
wordDulicate.add("bangalore");
wordDulicate.add("mumbai");
wordDulicate.add("mumbai");
wordDulicate.add("goa");
wordDulicate.add("calcutta");
wordDulicate.add("hyderabad");
ArrayList<String> nonDupList = new ArrayList<String>();
Iterator<String> dupIter = wordDulicate.iterator();
while(dupIter.hasNext())
{
String dupWord = dupIter.next();
if(nonDupList.contains(dupWord))
{
dupIter.remove();
}else
{
nonDupList.add(dupWord);
}
}
System.out.println(nonDupList);
}
}
A HashSet is implemented in terms of a HashMap anyway. If you specifically want to use a HashMap, use it the same way as HashSet does: use a dummy constant new Object() as the map value everywhere.
Well a HashMap will prevent you from entering duplicate keys, the same way as HashSet. Actually, many implementations of HashSet just use a HashMap under the hood.
So you can do:
HashMap<String, String> map = new HashMap<String, String>();
for (String s : WordDuplicate)
map.put( s, s );
Now you can access the key/values just like a HashMap.
import java.util.HashSet;
import java.util.Stack;
public class stackdupes {
public static void main(String[] args) {
Stack<Integer> st = new Stack<Integer>();
int[] arr= {1,2,3,3,4,5,5,7};
HashSet<Integer> set = new HashSet<Integer>();
for (int i=0;i<arr.length;i++) {
if(set.add(arr[i]) == true)
st.push(arr[i]);
}
System.out.println(st);
}
}