I first had the following code
with the following error message
java.util.ConcurrentModificationException
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:894)
at java.util.HashMap$KeyIterator.next(HashMap.java:928)
at ca.on.oicr.pinery.lims.gsle.GsleClient.getOrders(GsleClient.java:720)
Where line 720 is the second for loop.
I got the answer that I am adding to orders inside a loop that's looping over the elements of orders, that's what causes the exception. Don't modify a collection you're looping over inside the loop. Likewise with samples.
So I re-did this method but I get the following error message:
java.util.NoSuchElementException
java.util.NoSuchElementException
at java.util.ArrayList$Itr.next(ArrayList.java:794)
at ca.on.oicr.pinery.lims.gsle.GsleClient.getOrders(GsleClient.java:730)
Where line 730 is Set samples = sampleOrderMap.get(it.next().getId()) in my following code
How would I fix this error message, and will this new method have the same functionality of my original method that did not work, I feel that having all these loops and conditional statements will cause it to not work.
In the following code fragement:
while (it.hasNext()) {
if (sampleOrderMap.containsKey((it.next().getId()))) { // calling it.next()
if (it.next().getId() != null) { // again calling it.next() ?
Set<OrderSample> samples = sampleOrderMap.get(it.next().getId()); //again calling
for (OrderSample orderSample : samples) {
Set<Attribute> attributes = attributeOrderMap.get(orderSample.getId());
////............ your code
You are consecutively calling it.next() upon each call of iterator.next(), the iterator advances by one element by returning it. Though i am not sure what object it.next() is returning, but you can assign it to a Object of the collection type and use it inside the while loop as follows:
while (it.hasNext()) {
Order order = (Order)it.next(); // if Order is your list's type
if (sampleOrderMap.containsKey((order.getId()))) {
if (order.getId() != null) {
Set<OrderSample> samples = sampleOrderMap.get(order.getId());
for (OrderSample orderSample : samples) {
Set<Attribute> attributes = attributeOrderMap.get(orderSample.getId());
I'm assuming it is an Iterator. (I say that because you did not post the entire source code needed to reproduce this, which you should really do in the future.)
So each time you call it.next() you are advancing that iterator. You are calling it.next() three times in the first four lines. So if there's only one item left in the Iterator, the initial call to it.hasNext() will return true but you'll only be able to call it.next() once more before running out of items.
while (it.hasNext()) {
OrderSample nextSample = it.next();
// blah blah blah
// use nextSample instead of it.next() in each subsequence instance.
}
Related
For 2 days I'm pretty confused about .hasNext(); and next(); methods of Iteration interface especially in while loop. Let me give an example:
import java.util.*; // imported whole java.util package.
class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>(); // created ArrayList which name is cars.
cars.add("Volvo");
cars.add("Mercedes");
cars.add("BMW");
Iterator<String> x = cars.iterator();
while(x.hasNext()) {
System.out.print(x.next() + " "); // It prints Volvo Mercedes BMW
}
}
}
I understood that .hasNext(); is boolean and it returns true if iteration has elements. The .next(); method returns the next element. After first element Volvo, it gets back while(x.hasNext()) and entering the inside of loop again but where is the counter of this loop? I mean after printing Volvo how can it goes to the next element? It returns all element and if there is no more .hasNext(); returns false and code continues to next line is simple answer and correct but I want to understand it clearly.
Actually the iterator() Method Creates an iterator for all elements in your (let's say) Arraylist. Now in Your Code, the condition of while loop x.hasNext() checks whether the list contains an element or not, if yes it will return true else false.
Now x.next() point to First Element (Like of LinkedLists for example) in Your ArrayList and store that Object(Volvo in your case). When You Call this method it basically gives you reference of that object in List and the Iterator Moves to next element in the List. When Calling next() method the iterator(x in your case) returns the object and then moves to next Element (Mercedes in your case).
Now When you call next() method Again you will find Mercedes is returned. To know How it Works type System.out.println(x.next()) thrice instead of while loop u will understand that it moves to next location. If you type System.out.println(x.next()) fourth time it will give exception because there is no element in your list furthur more. Exception in thread "main" java.util.NoSuchElementException This is the Exception.
That's why hasNext() method is used as it checks whether an element is there or not.
you can Compare this to printing of linkedlist(Data structure if you know) where we make one object point to head node print it and move to next node. Same Case is here it returns current element(object) and moves to next element(object).
while is java-ese for: Keep doing this until a thing changes.
It's a bit like this common household task:
How to wash dishes
Check if there are still dirty dishes on the right side of the counter.
If there are some, do the dishwash thing: Pick up the nearest dirty dish, and wash it, then stow it away on the left side of the counter, and go back to the start of this algorithm.
Otherwise (there are no dirty dishes), you are done.
while (counterRightSide.hasItems()) {
Dish dirty = counterRightSide.fetch();
Dish clean = sink.clean(dirty);
counterLeftSide.stow(clean);
}
EDIT: I realize now that 'a kitchen counter' is an unfortunate example, given the homonym 'kitchen counter' and 'counter in code'. I'll use 'accumulator' instead of 'counter in code' to fix this confusion.
Note how there is no accumulator here either, and you aren't counting in your head when you wash the dishes either. You COULD first take inventory of the amount of dirty dishes you have (say, 15 dishes), and then write a protocol where you grab a dirty dish exactly 15 times before decreeing that you've done the job, but surely you realize that that's just one way to do it, and another is to just... check if there are any dirty dishes left every time you're done washing 1 dirty dish. Which is how the above code works.
Note that the action of 'fetching' an item from the right side of the kitchen counter changes properties of that kitchen counter. It now has one less item on it.
The same applies to iterators: Calling .next() on an iterator changes it in some form. After all, if you call next twice, the results of these calls are different. Contrast with invoking, say, someArrayList.get(5) a bunch of times in a row; that doesn't change the arraylist at all, and therefore you get the same thing back every time. next() is not like that.
So how DOES that work? Who counts this stuff?
Well, that's the neat thing about abstraction! A 'Collection' is something that can do a few things, such as 'it must be able to report to how how many items it holds', and, 'it must be able to festoon you an object that can be used to loop through each item that it holds'.
That's what an iterator is: An object that can do that.
So how does it work? Who knows! It doesn't matter! As long as you CAN do these things, you can be a collection, you are free to implement the task however you like.
Okay, but how does a common collection, like, say, ArrayList do this?
With a counter, of course. Here's the implementation:
public Iterator<T> iterator() {
return new Iterator<T>() {
int counter = 0; // here it is!
public boolean hasNext() {
return counter < size();
}
public int next() {
return get(counter++);
}
};
}
you're getting this object and referencing it in your code (your x variable), and that object has a field with a counter in it. You can't see it; it's private, and not actually in the Iterator type (Iterator is an interface; what you get is some unknown subtype of it, and that contains the counter variable). That's assuming you're getting an iterator by invoking .iterator() on an arraylist. If you invoke it on something else, there may or may not be a counter - as long as the iterator WORKS, it doesn't matter how it works, that's the beauty of interfaces.
A while loop checks the condition and when condition is true then executes the body of the loop and iterates itself,
while(condition){
//do something.
}
The hasNext() is a method from the Iterator interface which returns true if the "iteration" has more elements, if there are no more elements it returns fals and will no longer enter the body of the while loop:
while(x.hasNext){
//do something.
}
The next() method is a method from the Iterator interface and returns the next element of the iteration.
while(x.hasNext){
x.next();
}
I mean after printing Volvo how can it goes to the next element? It
returns all element and if there is no more .hasNext(); returns false
and code continues to next line is simple answer and correct but I
want to understand it clearly.
int cursor; // index of next element to return
//...
public boolean hasNext() {
return cursor != size;
}
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
//...
Given above is how ArrayList#hasNext and and ArrayList#next have been implemented. The code is straight forward and easy to understand. You can check the full code by using a decompiler or here.
I have read that Iterator .next() method returns the object, but I get an error saying it is not a statement. I am pretty new to Java, so help would be very appreciated!
I have tried with both Iterator, Iterator and ListIterator. I get the same error. My code is for homework and is pretty long, so I will just add what I think is most relevant here. Please ask if you need to see more!
Iterator<Person> itr = work.iterator();
while (itr.hasNext()){
Person this = itr.next();
if (this.birthday == time){
if (once == 0){
System.out.println("Birthday: "+time);
once++;
}
work.remove(this);
As you can see I am using the stored object multiple times, so I don't think I can use itr.next() several times as it will move to the next value.
My error:
Homework4.java:145: error: not a statement
Person this = itr.next();
This question already has answers here:
Calling next on an Iterator once vs multiple times
(3 answers)
Closed 7 years ago.
I had some trouble with the whole iterator concept and for a question in one of my quizzes, I honestly couldn't understand what was up.
public static void main(String[] args)
{
Deque<String> SQ1 = new ArrayDeque<String>();
SQ1.add("Give");
SQ1.add("Me");
SQ1.add("The");
SQ1.add("Best");
SQ1.add("Of");
SQ1.add("Both");
SQ1.add("Worlds");
Iterator<String> It = SQ1.iterator();
while(It.hasNext())
{
if(It.next().equals("Give"))
System.out.print(It.next());
}
}
This is the code, and the question is what will be the output. The correct answer is "Me" when I thought it was "Give". I don't understand how the whole run goes.
This is what I understand:
It does have a next. If that next equals "Give", it will print out that next value. In this case, that value should be "Give", shouldn't it?
Could someone please help me understand this?
The if-statement calls It.next() to check the value, and the the print statement calls It.next() again, rather than printing the value that you just checked.
So what you see will always be the element directly after "Give".
The correct answer is "Me" when I thought it was "Give". I don't understand how the whole run goes.
Right, the code is illustrating a common error. The error is that the code is telling the iterator to advance to the next item and give it to us twice:
Iterator<String> It = SQ1.iterator();
while(It.hasNext())
{
if(It.next().equals("Give"))
// here^^^^^^^^^
System.out.print(It.next());
// and here -------------^^^^^^^^^
}
So it's getting the value, seeing if it's "Give", and then if that value was "Give" it throws it away and gets the next value, which in your test data is "Me". (Note that if "Give" were the last entry, that second call to next would throw an error, since there would be no next entry at that point.)
To "fix" it and have it show "Give", still using that kind of loop, you'd remember the result of the call in a variable, and then use the variable in those two places:
Iterator<String> It = SQ1.iterator();
while(It.hasNext())
{
String value = It.next();
if(value.equals("Give"))
System.out.print(value);
}
But, this is what the enhanced for loop is for: You don't use an It variable at all, just:
for (String value : SQ1) {
if(value.equals("Give"))
System.out.print(value);
}
As you can see from the Java docs:
next
E next()
Returns the next element in the iteration.
Returns:
the next element in the iteration
Throws:
NoSuchElementException - if the iteration has no more elements
So your call:
If(It.next().equals("Give"))
Actually returns the "next" value and sets the Iterator 'It' to the next one in your ArrayDeque.
If you call next again you will be one step further.
We all know that the safest "and probably only safe" way of removing an object from a collection while iterating it, is by first retrieving the Iterator, perform a loop and remove when needed;
Iterator iter=Collection.iterator();
while(iter.hasNext()){
Object o=iter.next()
if(o.equals(what i'm looking for)){
iter.remove();
}
}
What I would like to understand, and unfortunately haven't found a deep technical explanation about, is how this removal is performed,
If:
for(Object o:myCollection().getObjects()){
if(o.equals(what i'm looking for)){
myCollection.remove(o);
}
}
Will throw a ConcurrentModificationException, what does "in technical terms" Iterator.remove() do? Does it removes the object, breaks the loop and restart the loop?
I see in the official documentation:
"Removes the current element. Throws IllegalStateException if an
attempt is made to call remove() that is not preceded by a call to
next( )."
The part "removes the current element", makes me think of the exact same situation happening in a "regular" loop => (perform equality test and remove if needed), but why is the Iterator loop ConcurrentModification-safe?
The reason why you cannot modify a list while iterating over it is because the iterator has to know what to return for hasNext() and next().
How this is done is implementation specific, but you could have a look at the source code of ArrayList/AbstractList/LinkedList etc.
Also note that in some situations you can use some code like this as an alternative:
List<Foo> copyList = new ArrayList<>(origList);
for (Foo foo : copyList){
if (condition){
origList.remove(foo);
}
}
But this code will probably run slightly slower because the collection has to be copied (shallow copy only) and the element to remove has to be searched.
Also note that if you're using the iterator directly it's recommended to use a for loop instead of while loop as this limits the scope of the variable:
for (Iterator<Foo> iterator = myCollection.iterator(); iterator.hasNext();){
...
}
How exactly Iterator removes elements depends on its implementation, which may be different for different Collections. Definitely it doesn't break the loop you're in. I've just looked how ArrayList iterator is implemented and here's the code:
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
So it checks for concurrent modifications, removes element using public ArrayList remove method, and increments counter of list modifications so ConcurrentModificationException won't be thrown at next iteration.
I use Java 6 Collecetions API. I need a collection that should have only N elements. I mean that if I add new element and collection already have N elements than the last element should be removed and new one add in the head of collection. I have following code fragment to do it:
class A {
int N = 100;
Deque dq = new LinkedList();
void add(Object o) {
synchronized (o) {
if (dq.size() == N) {
dq.pollLast();
}
dq.add(o);
}
}
Deque getDq() {
return new LinkedList(dq);
}
}
Object with type A can be accessed many users in the same time to add new element. In practice I got NullPointerException with it:
Caused by: java.lang.NullPointerException
at java.util.LinkedList.remove(LinkedList.java:790)
at java.util.LinkedList.removeLast(LinkedList.java:144)
at java.util.LinkedList.pollLast(LinkedList.java:573)
at A.add(A.java:9)
Deque.pollLast() contract doesn't say anything about NullPointerException:
Retrieves and removes the last element
of this list, or returns null if this
list is empty.
Also adding of elements is synchronized.
Does anyone know what is reason of exception could be?
Thanks for any ideas
I guess the sycronization is done on the wrong object! It should be dq but not o!
... synchronized (dg) { ...
I've run your code adding using the following test
A a = new A();
for (int i = 0; i < 200; i++)
{
a.add(i);
}
System.out.println(a.dq);
And it all seems to work correctly. Can you provide more details on the state of the application when you get the NPE? What is the object you are trying to add? What is the state of the Dequeue at that time?
Also, you mentioned
if I add new element and collection
already have N elements than the last
element should be removed and new one
add in the head of collection
Your code doesn't do that. Right now, it adds to the tail of the collection. To add it to the head, change
dq.add(o)
to
dq.addFirst(o)
see this javadoc it says
Removes and returns the last element from this list.
first it removes object so if it is null then throws NullPointerException:
so make add(..) method synchronized and check for size before dq.pollLast();