Illegal state Exception Occurring with ArrayList [duplicate] - java

This question already has an answer here:
IllegalStateException when removing an object with iterator
(1 answer)
Closed 5 years ago.
I was trying to run the below code in my system and encountered Illegal State Exception while doing so.
import java.util.*;
public class ArraylistExample2
{
public static void main(String args[])throws Exception
{
ArrayList <String> al = new ArrayList<String>();
al.add("A");al.add("B");al.add("C");
Iterator <String> i = al.iterator();
while(i.hasNext())
{
if(al.contains("B"))
{
i.remove();
System.out.println(" Element B removed");
}
System.out.println(i.next());
}
}
}
Can someone please explain what is wrong with the code here or what method has been illegally called giving rise to this exception ? Below is the stack Trace:
java.lang.IllegalStateException
at java.util.ArrayList$Itr.remove(ArrayList.java:864)
at collectionsExamples.ArraylistExample2.main(ArraylistExample2.java:17)

The cursor hasn't moved to an element yet. You just checked whether there is an element or not.
You are removing an element from iterator before actually starting the iteration. Hence there is no current element in the iterator to remove.
First move the cursor for next element and then try to remove it if the criteria matched.
So, the modified code looks like
while(i.hasNext())
{
Strng s = i.next(); // note this
if(al.contains("B"))
{
i.remove();
System.out.println(" Element B removed");
}
System.out.println(s);
}

Here is the correct implementation, you need not to check if(al.contains("B")) rather check if the elemnent value is B
import java.util.*;
public class ArraylistExample2
{
public static void main(String args[])throws Exception
{
ArrayList <String> al = new ArrayList<String>();
al.add("A");al.add("B");al.add("C");
Iterator <String> i = al.iterator();
while(i.hasNext())
{
String element=i.next();
if("B".equals(element))
{
i.remove();
System.out.println(" Element B removed");
}
}
}
}

Related

Removing element in ArrayList using INDEX causing java.util.ConcurrentModificationException

The following code is causing
java.util.ConcurrentModificationException
I am not sure how to solve the error please help !
ArrayList strList = new ArrayList<String>(Arrays.asList(cmd.split(" ")));
if (strList.get(0).equals("LIST")) {
}
if (strList.get(0).equals("DEPEND")) {
strList.remove(0); // getting error at this point
cm.createComponent(strList);
}
Full Method The outer loop is not related to the List
public static void main(String[] args) throws IOException {
ComponentManager cm = new ComponentManager();
List<String> lines = Files.readAllLines(Paths.get("cmdList.txt"));
for (String cmd : lines) {
ArrayList strList = new ArrayList<String>(Arrays.asList(cmd.split(" ")));
if (strList.get(0).equals("LIST")) {
}
if (strList.get(0).equals("DEPEND")) {
strList.remove(0);
cm.createComponent(strList);
}
if (strList.get(0).equals("INSTALL")) {
}
if (strList.get(0).equals("REMOVE")) {
}
}
}
You can create a different ArrayList and perform remove operation there or put up an iterator on the arrayList and remove using the iterator.
Find a couple of potential solutions to your problem here and here.

Converting Collections to Strings, getting invalid method declaration

I'm working on an assignment and I feel super close! But I just don't understand the last error message I'm getting and was wondering if you could help me understand it so I avoid it in the future.
The assignment started off with an example code:
import java.util.*;
public class Proj09{
public static void main(String args[]){
new Proj09Runner().getCollection();
}
}
class Proj09Runner{
public void getCollection(){
Collection collection = new TreeSet();
Populator.fillIt(collection);
Iterator iter = collection.iterator();
while(iter.hasNext()){
System.out.print(iter.next());
}
System.out.println();
}
}
class Populator{
public static void fillIt(Collection collection){
collection.add("Able");
collection.add("Baker");
collection.add("aBle");
collection.add("Charley");
collection.add("Baker");
}
}
Output: Able Baker aBle Charley Baker
And our job is to change that code so that it fits a different main that I'm not able to edit:
import java.util.*;
public class Proj09{
public static void main(String args[]){
Proj09Runner runner = new Proj09Runner();
Collection <String> collection = runner.getCollection();
collection.add("Able");
collection.add("Baker");
collection.add("aBle");
collection.add("Charley");
collection.add("Baker");
Iterator <String> iter = collection.iterator();
while(iter.hasNext()){
System.out.print(iter.next() + " ");
}
System.out.println();
}
}
So far, I've been playing with the Proj09Runner class:
class Proj09Runner extends Proj09{
public void getCollection(){
System.out.println("My Name.");
System.out.println();
}
}
Small change to the output, I'm supposed to add my name.
Desired output:
My Name
Able Baker aBle Charley Baker
But I keep getting different errors that go back to the line Collection <String> collection = runner.getCollection(); in the main I'm not supposed to change. I'll get called out on void's not being able to be converted to Collection <String> or "invalid method declaration; return type required."
Could y'all help me figure out why I'm getting those messages and what they mean so that I can avoid them in the future?
Thanks, I really do appreciate it.
This for sure needs improvement :
Collection <String> collection = runner.getCollection();
this does not return a Collection<String>, note your method returns nothing.
public void getCollection(){
Either your method return type and definition changes something like :
public Collection<String> getCollection(){ //followed by corresponding definition
Or you can simply use
Collection <String> collection = new HashSet() ; //whatever your collection pertain to
public Collection<String> getCollection(){
Collection collection = new TreeSet();
Populator.fillIt(collection);
Iterator iter = collection.iterator();
while(iter.hasNext()){
System.out.print(iter.next());
}
System.out.println();
return collection;
}
your getCollection method is returning nothing. it should return a collection
I've been trying this and it seems to be a good direction. Keeping the main:
import java.util.*;
public class Proj09{
public static void main(String args[]){
Proj09Runner runner = new Proj09Runner();
Collection <String> collection = runner.getCollection();
collection.add("Able");
collection.add("Baker");
collection.add("aBle");
collection.add("Charley");
collection.add("Baker");
Iterator <String> iter = collection.iterator();
while(iter.hasNext()){
System.out.print(iter.next() + " ");
}
System.out.println();
}
}
I've now got:
class Proj09Runner{
public Collection<String> getCollection(){
return "Hailey";
}
}
I didn't want to reiterate what was already in the main as it seemed unnecessary. Returning the string "Hailey" addressed the old error, but a new one has popped up.
error: cannot find symbol
public Collection<String> getCollection(){
^
symbol: class Collection
location: class Proj09Runner
Do you know what that type of error indicates?
Our last unit was about inheritance, and I played with "Proj09Runner extends Proj09{" but it didn't seem to have an effect.
I wanted to go ahead and share the answer:
import java.util.*;
class Proj09Runner{
public Collection <String> getCollection(){
System.out.println("Name.");
Collection collection = new ArrayList();
return collection;
}
}
I couldn't go with TreeSet because it doesn't accept duplicates and so would only print "Baker" once, so I went with ArrayList instead.
Thanks a bunch for the feedback!

How to remove element from ArrayList?

I have added data into ArrayList and now want to update that list be deleting some element from it.
I have element something like 1,2,3,4 in ArrayList of type CartEntry.
Code :
ArrayList<CartEntry> items = new ArrayList<CartEntry>();
public void remove(int pId)
{
System.out.println(items.size());
for(CartEntry ce : items)
{
if(ce.getpId() == pId)
{
items.remove(ce);
//System.out.println(items.get(1));
}
}
items.add(new CartEntry(pId));
}
CartEntry Code :
public long getpId() {
return pId;
}
Constructor :
public CartEntry(long pId) {
super();
this.pId = pId;
}
when I am trying this code it gives me an error:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
Here pId is the argument that specify that item should be deleted from items.
Suppose I want to delete item that have 2 data then what will I have to do ?
You are facing ConcurrentModificationException because you are doing two operations on the same list at a time. i.e looping and removing same time.
Inorder to avoid this situation use Iterator,which guarantees you to remove the element from list safely .
A simple example looks like
Iterator<CartEntry> it = list.iterator();
while (it.hasNext()) {
if (it.next().getpId() == pId) {
it.remove();
break;
}
}
There are at least two problems with your code:
you call remove on the collection you iterate over, that will cause a ConcurrentModificationException if you continue iterating after the remove.
There are two ways to fix this:
stop iterating after you found the object you want to remove (just add a break or a return) or
switch from the enhanced for-loop to using an Iterator and its remove method.
you add an element in your remove method, that's probably not what you want.
So I'd use this code (this assumes that there is only ever one CartEntry with a given id in the list):
public void remove(int pId)
{
for(CartEntry ce : items)
{
if(ce.getpId() == pId)
{
items.remove(ce);
return;
}
}
}
If the assumption with the unique id is not correct, then you'll need to use the Iterator approach:
public void remove(int pId)
{
Iterator<CartEntry> it = items.iterator();
while(it.hasNext())
{
CartEntry ce = it.next();
if(ce.getpId() == pId)
{
it.remove();
}
}
}
you have created an Arraylist of type carEntry. So you need to create an Iterator of type CarEntry
Iterator<CarEntry> it = items.iterator();
while(it.hasNext())
{
if(it.next().getPId == PId)
it.remove();
}
Implement .equals in CartEntry and then use ArrayList.remove(CartEntry) or loop through your array list, find the item with some condition, mark the index, and call ArrayList.remove(index) -- AFTER the loop
Try,
public void remove(int pId){
Iterator<CartEntry> it = items.iterator();
while(it.hasNext()) {
CartEntry entry = it.next();
if (entry.getpId() == pId) {
it.remove();
}
}
}
The enhanced-for(or for each) loop for iterating over an Expression which is a subtype of Iterable<E> or raw Iterable, basically equivalent to the following form:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableIdentifiers_opt TargetType Identifier = (TargetType) #i.next();
Statement
}
This is clearly stated in jls 14.14.2. The enhanced for statement section.
For your context the Expression is an ArrayList. the iterators returned by ArrayList's iterator method is 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.
use an Iterator instead and use it's own remove() method:
Iterator<E>iterator = list.iterator();
while(iterator.hasNext())
if(iterator.next().equals(E))
iterator.remove();

what is causing my NoSuchElementException for ArrayList

I know that there are lots of threads on NoSuchElementException in Java here but I still cannot figure out what is going on here
I am trying to come up with a solution for Transitive Dependencies Kata 18 which is posted at http://codekata.pragprog.com/2007/01/kata_eighteen_t.html
dependencies_for method is supposed to take in a char item and compute all dependencies for the item. The exception occurs when I try to add an element to finalDependencies ArrayList
This is the place where my NullPointerException occurs. I have traced all of these data structures and none of them have a Null value. I don't understand what is causing my exception here. Please see my code:
public class Test_Dependencies
{
public static void main(String[] args) {
Dependencies Dep = new Dependencies();
Dep.add_direct('A', "B C");
Dep.add_direct('B', "C D");
Dep.dependencies_for('A');
}
}
public class Dependencies {
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
public void add_direct(char mainItem, String dependentItems)
{
// code that works here
}
public String dependencies_for(char item)
{
ArrayList finalDependencies = new ArrayList<Character>();
Character key = new Character(item);
//get initial dependencies for the item and add them
ArrayList processingDependencies = dependenciesList.get(key);
Iterator itr = processingDependencies.iterator();
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// look again at each item in dependenciesList. If it is in the list then add it to processingDependencies
if(dependenciesList.containsKey(itr.next()) && !processingDependencies.contains(itr.next()))
{
processingDependencies.add(itr.next());
}
}
}
// turn finalDependencies into a string
itr = finalDependencies.iterator();
String allDependencies = "";
while(itr.hasNext())
{
allDependencies = allDependencies + " " + itr.next();
}
return allDependencies;
}
}
I am a bit perprlexed because processingDependencies and finalDependencies ArrayLists are not null. And processingDependencies arraylist contains an item
You are calling twice. The first call is "protected" by a matching hasNext Call. The second is not. Save the result of next into a temporary variable and use that, instead of using the value directly, since every call to next will try to advance the iterator first. In the good case, you get an exception. In the bad case, things seem to work, but your program is dealing with the wrong value.
You can't do this:
while(itr.hasNext())
{
if(finalDependencies.contains(itr.next()) == false && itr.next() != key)
{
// NoSuchElement exception here
finalDependencies.add(itr.next());
// stuff removed
}
}
You must verify that iter.hasNext() is true prior to each call of itr.next(). What happens when you reach the last item in itr, but then call itr.next() three times?
Answer: NoSuchElementException. Check out Iterator
The problem is here:
HashMap dependenciesList;
public Dependencies()
{
HashMap<Character, ArrayList> dependenciesList = new HashMap<Character, ArrayList>();
}
You declare a hashmap called dependenciesList. You then try to instantiate that list, but what you actually do is create a local variable named the same thing. They are two separate variables. Then you try to use the one that hasn't been instantiated here:
ArrayList processingDependencies = dependenciesList.get(key);
What you need to do is instantiate the first dependenciesList instead of creating a new one
(I'm not a pro at java, but something like dependenciesList = new HashMap....() instead of HashMap<..> dependenciesList = new HashMap...() )

Iterating a Collection more than once

I am having trouble using Iterator in java.
it=myHash.iterator();
while (it.hasNext())
if (it.next() satisfying something)
do something
while (it.hasNext())
if (it.next() satisfying something)
it.remove();
I am trying to iterate hashset twice, and the first loop making it.hasNext() return false. How to i resolve this?
I tried even adding the edit as you guys suggested, still not working...
You're reusing the same iterator - and that's been invalidated by adding new items to the set.
You should call iterator() again on the set:
it = set.iterator();
You can't reset the existing iterator
EDIT: Here's some sample code which shows this working:
import java.util.*;
public class Test {
public static void main(String[] args) {
Set<String> set = new HashSet<String>();
set.add("food");
set.add("bad");
set.add("hungry");
set.add("neighbour");
Iterator<String> it = set.iterator();
// Remove any string longer than 4
while (it.hasNext())
{
if (it.next().length() > 4)
{
it.remove();
}
}
set.add("new long text");
set.add("x");
// Remove any string shorter than 4
it = set.iterator();
while (it.hasNext())
{
if (it.next().length() < 4)
{
it.remove();
}
}
// Dump the results
for (String x : set)
{
System.out.println(x);
}
}
}
This gives the results "new long text" and "food".
Ideally, what you are looking for is a reset operation on an Iterator. Iterators are meant to be unidirectional and one-time use, as such they don't have support for reset in Java.
You can either get hold of a new Iterator instance or use ListIterator interface which allows you to look backwards using previous().
Edit:
You are using remove() on the iterator which is also removing elements from the original set. In such a case you should consider making a copy of the set since you want to iterate over the elements all over again:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
public class IteratorSnippet {
public static void main(String[] args) {
final HashSet<Integer> myHash = new HashSet<Integer>();
myHash.addAll(Arrays.asList(1, 2, 3, 4, 5));
// make copy before using iterator with remove
final HashSet<Integer> myHash2 = new HashSet<Integer>(myHash);
Iterator<Integer> it = myHash.iterator();
System.out.println("First go...");
while (it.hasNext()) {
System.out.println(it.next());
it.remove();
}
it = myHash2.iterator();
System.out.println("Second go...");
while (it.hasNext()) {
System.out.println(it.next());
}
}
}

Categories

Resources