I have difficulty in using hasNext() iterator method. I have a JSONArray:
JSONArray = [{"a":1},{"b":2,"c":3}]
I am accessing one JSONObject at a time. First JSONObject in the JSONarray has one element second have two elements. The issue is that when the iterator check hasNext() on first JSONObject with one element it gives true, my understanding is that it should give true only if it has more elements then the present one. Please help and clarify this.
for (int i=0; i<JArrayLength; i++) {
JSONObject obj = newJArray.getJSONObject(i);
Iterator k = obj.keys();
System.out.println("Value k.hasnext is = " + k.hasNext());
if(k.hasNext())
{ //print somehting} // here its printing but as the value should be false it should not for i=0.
}
Please suggest where am I going wrong.
You open the iterator
Iterator k = obj.keys();
and then immediately check to see whether it has keys. Since you haven't consumed the first key (a), of course it does.
Note also that you're getting warnings about using the raw type Iterator. Pay attention to them and parameterize appropriately (probably with <String>).
hasNext checks the iterator if it has any values to iterate to actually get the value you should do:
if(k.hasNext()){
k.next(); // gets the actual value
}
hasNext() Returns true if the iteration has more elements.
next() Returns the next element in the iteration.
Related
I have an if-else function within a for loop iterating through a list. When I reach the last element of this list, I want it to undertake an action, but it doesn't seem to be working. Here is an outline of my code:
for(Item t: itemList){
if(....){
}
else if(....){
}
else if(currentStartTime>previousFinishTime){
System.out.println("C");
if(itemList.iterator().hasNext()==false){
System.out.println("end of array");
EFTs.add(EFT);}
else{.....;}
}
When I trigger this condition with the last item in the list (i.e. the last item has currentStartTime>previousFinishTime, I know this is correct because it prints C), nothing in my if condition triggers. Have I misunderstood the purpose of the hasNext() function?
Thanks
itemList.iterator().hasNext()==false
itemList.iterator() refers to a brand new iterator. It doesn't refer to the iterator being used in the for loop. itemList.iterator() will in fact always start at the beggining of the list, and thus hasNext() will tell you if the list is empty.
To use an iterator like this, you need to make your own loop, something like:
for(Iterator<Item> iter = itemList.iterator(); iter.hasNext(); ) {
Item item = iter.next();
if(iter.hasNext()) {
}
}
But 95% of the time, you should be able to do whatever you want after the loop instead of during the last iteration.
With the "enhanced for", you cannot access the operator created for the for operation.
What you are doing is creating a new operator each time, so it points to the start of the list. Obviously, unless it is an empty list, it will return true for hasNext().
I have this iterator,
Set<BigFraction> key = knowledgeD.keySet();
TreeSet<BigFraction> sortKey = new TreeSet<BigFraction>();
sortKey.addAll(key);
Iterator<BigFraction> iter = sortKey.iterator();
return iter;
BigFraction is just the data type if it makes it any easier just sub this with int or something.
Anyway when i called the iterator later on to
while (iterator().hasNext());
It basically just gives me an infinite loop of somesort... and when i printout iterator() before this while loop i get
java.util.TreeMap$KeyIterator#53b4b24d
Any idea's kind of stuck,
Regards,
Sim
You need to use your Iterator like this:-
while (iter.hasNext()) {
System.out.println(iter.next()); //Do whatever you want
}
where hasNext() tells if the iterator has more values or not, and next() returns the next value in the iterator.
Also, the explanation of why your current iterator loop is not working(going into an infinite loop), has been explained by #jacobm.
iterator().hasNext() never advances the iterator, it just checks to see if it has an element. So while (iterator().hasNext()); will always infinite-loop if there are any values to iterate over. You can fix it with:
Iterator<BigFraction> it = iterator();
while (it.hasNext()) {
it.next();
}
The call to iterator() constructs a new iterator, so your code will construct a new iterator each time through the loop. Instead try something like:
Iterator it = iter;
while (it.hasNext()) {
it.next()
}
Be sure to call next() each time through the loop, otherwise you won't increment the iterator, and it will just stay on the first item.
Iterator#hasNext returns true if the iteration has more elements, it does not return the next element in the iteration. which Iterator#next does.
If you use itarator if you must call iterator#next to get the next element of collection, but hasNext is operation is optional.
you could either write -
while (iter.hasNext()) {
Object oj = iter.next();
}
or
Object obj = null;
while ( (obj = iter.next())!=null) {
....
}
with this approach hashNext is not at all required.
When using iterator in Java, the last iterator is pointing one past the last node right? And the value is null right?
Then when using
iter = myList.listIterator();
sum = 0;
while (iter.hasNext()) {
sum += iter.next();
}
Shouldn't there be a off-by-one problem since the last value iterator is pointing at is null? I know in fact is there's no such off-by-one problem, but don't know why, please explain this for me. Thanks in advance!
Edit: sorry, too excited, didn't type complete code.
Summary: Hope this helps for future people, I was thinking about iterators as pointers in C++, but actually even if imagined as pointers, instead of pointing to nodes, they 'point' to the space between nodes (space before a node to be more precisce) as bmorris591 described.
next() moves the Iterator along, hasNext() only checks if there is a next. The Iterator doesn't "point", if anything it points at the spaces between elements.
You may want to read up on the Iterator Pattern.
There is no null element returned from an Iterator when hasNext returns false.
Conceptually, when hasNext returns false, the iterator is pointing "past" the last element already, but there is nothing "past" the last element, not even null.
If you call next when hasNext returns false, then it won't return null -- it will throw a NoSuchElementException.
An iterator iterates over the list. The method hasNext() returns true when there are still elements left to iterate over and false when all elements have been processed. An example:
A list with contents [0,2,4]:
iter = myList.listIterator();
iter.hasNext(); // true
iter.next(); // returns 0
iter.hasNext(); // true
iter.next(); // returns 2
iter.hasNext(); // true
iter.next(); // returns 4
iter.hasNext(); // false
Thus there is no problem with off-by-one or something like that. Whenever hasNext() returns true, there are still elements left to iterate over; next() returns that element.
Assuming your list contains Integer instances, you can do something like the following:
Iterator <Integer> iter = myList.listIterator();
int sum = 0;
while (iter.hasNext()) {
sum += iter.next().intValue();
}
your code will add the result of each iter.next() to sum on each iteration of the loop.
When iter.hasNext() is called, it is not "at the first value", but just before the first value - the first call will then return that first value and update the internal state of the iterator to be just before the second value (just after the first value).
When you get to the end, the internal state is pointing to just after the last value, so iter.hasNext() returns false and your loop exits.
Now, if your iterator contains any null values, they are still returned by the calls to next(), and you'll end up with a NullPointerException (which you can avoid with a simple null check).
I want to remove all elements in ArrayList that are duplicates of the first element, but I want the firs element to remain in the ArrayList. I tried to do that with for loop, but it didn't remove all duplicates.
for(int i = 1; i < arraylist.size(); i++) {
if(arraylist.get(i) == v1)
arraylist.remove(i);
}
v1 is equal to the first element of the arraylist.
I also tried with ListIterator, but it removed the first element
ListIterator<Integer> iterator = arraylist.listIterator();
while(iterator.hasNext()) {
if(iterator.next().intValue() == v1)
iterator.remove();
}
Can you please help me?
You need to read the first element separately, outside the while loop, and store it in some variable, with which you would compare the rest of the elements, to remove:
ListIterator<Integer> iterator = arraylist.listIterator();
int first = 0;
// Check if there is a first element
if (iterator.hasNext()) {
first = iterator.next();
// Iterate over the rest of the elements
while(iterator.hasNext()) {
// If this value is equal to `first`, remove it
if(iterator.next().intValue() == first) {
iterator.remove();
}
}
}
System.out.println(arrayList);
iterator.next() will return a value of type Integer. Using intValue() will give your primitive value out.
But since I'm doing the comparison with an int primitive itself, you won't need to call intValue() at all. Your Integer will automatically be unboxed to primitive int before comparison. So, replacing the if statement in while with the below one will also work:
if(iterator.next() == first) {
iterator.remove();
}
As far as your first way is concerned, I would say, always use Iterator if you want to modify the List you are looping upon. This will prevent you from facing awkward ConcurrentModificationException.
See also:
Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop
You are doing the correct way by using Iterator and its method remove. But you should add a call to next() before the loop itself, in order to go over the first element and not remove it.
ListIterator<Integer> iterator = arraylist.listIterator();
iterator.next(); // pass the first element.
while(iterator.hasNext()) {
if(iterator.next().intValue() == v1)
iterator.remove();
}
Contrary to what others have said, you don't have to use "equals" if v1 is an int, which seems to be the case.
Count down (not up):
Object v1 = arraylist.get(0);
for (int i = arraylist.size() - 1; i > 1; i--) {
if (arraylist.get(i).equals(v1))
arraylist.remove(i);
}
You have to count down because as you remove elements, they the remaining ones shuffled down.
Also, you should change == to .equals() (as shown).
int v1 = arraylist.get(0);
for(int i = 0; i < arraylist.size(); i++) {
if(arraylist.get(i) == v1){
arraylist.remove(i);
i--;
}
}
If you don't want to use the Iterator approach: The other answers are correct in that you need to index from zero (if you want to remove the first one as well), but you also need to decrement your iteration variable (the i-- line) each time you remove an element from the list, because you're changing the list's length with remove().
It's best to be careful about removing elements from an array (or an iterable list) whilst iterating over it.
Easiest approach, in my experience, is to create a new list. Can you consider doing that?
Looking at your code, firstly remember to use "equals" over "==" for comparison (since .equals means "meaningfully equivalent", which I think is what you need here). (edit: may not matter here due to autoboxing, but it's still a nice habit to have)
But even this won't work:
for (int i = 1; i < arraylist.size(); i++) {
if (arraylist.get(i).equals(v1))
arraylist.remove(i);
}
Since imagine you have an ArrayList of three integers, all the same. When i == 1, The element at index 1 is compared to the value at index 0, and removed. But then the element at index 2 becomes the element at index 1, the for-loop counter is incremented, thereby "missing" to remove the last entry in the list.
Can I recommend something like this?
List<Integer> newlist = new ArrayList<Integer>();
newlist.add(v1);
for (Integer integer : arraylist) {
if (!integer.equals(v1))
newlist.add(integer);
}
Best of luck!
P.S. if you're feeling brave, you might be able to do a neat one-liner out of this:
CollectionUtils.filter(Collection,Predicate)
CollectionUtils.filter(arraylist.subList(1, arraylist.size()), new Predicate() {
#Override
public boolean evaluate(Object o) {
return !v1.equals(o);
}
});
I love to use a for loop with the iterator principle, like
for(String s : collectionWithStrings)
System.out.println(s + ", ");
Question: How can I determine if the current element is the last one?
With an own index like int = 0; i < collection.size(); i++ this is possible with i == collection.size() - 1, but not nice. Is it also possible to determine the last element with an iterator for the example above?
Indeed, the Iterator#hasNext method returns a boolean determining if the iterator will return another element with the next method.
Your iteration can be put as this:
Iterator<String> iterator = collectionWithString.iterator();
while(iterator.hasNext()) {
String current = iterator.next();
// if you invoke iterator.hasNext() again you can know if there is a next element
}
Just use the hasNext method.
if(!iterator.hasNext()) {
// this is the last element
}
Normally, we iterate using an Iterator as so:
while(iterator.hasNext()) {
Object obj = iterator.next();
}
It's not possible with an enhanced for loop without maintaining your own counter. To be honest, this is my one deciding factor when I choose which type of for loop to use.
When using an Iterator, one has access to the hasNext() method which will return false when you are processing the last element.