I am using an Iterator to iterate through a collection
and I want to get the current element's index.
How can I do that?
I had the same question and found using a ListIterator worked. Similar to the test above:
List<String> list = Arrays.asList("zero", "one", "two");
ListIterator<String> iter = list.listIterator();
while (iter.hasNext()) {
System.out.println("index: " + iter.nextIndex() + " value: " + iter.next());
}
Make sure you call the nextIndex() before you actually get the next().
Use your own variable and increment it in the loop.
Here's a way to do it using your own variable and keeping it concise:
List<String> list = Arrays.asList("zero", "one", "two");
int i = 0;
for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {
String s = it.next();
System.out.println(i + ": " + s);
}
Output (you guessed it):
0: zero
1: one
2: two
The advantage is that you don't increment your index within the loop (although you need to be careful to only call Iterator#next once per loop - just do it at the top).
You can use ListIterator to do the counting:
final List<String> list = Arrays.asList("zero", "one", "two", "three");
for (final ListIterator<String> it = list.listIterator(); it.hasNext();) {
final String s = it.next();
System.out.println(it.previousIndex() + ": " + s);
}
What kind of collection? If it's an implementation of the List interface then you could just use it.nextIndex() - 1.
Use an int and increment it within your loop.
just do something like this:
ListIterator<String> it = list1.listIterator();
int index = -1;
while (it.hasNext()) {
index++;
String value = it.next();
//At this point the index can be checked for the current element.
}
Use a ListIterator to iterate through the Collection. If the Collection is not a List to start with use Arrays.asList(Collection.toArray()) to turn it into a List first.
All you need to use it the iterator.nextIndex() to return the current index that the iterator is on. This could be a bit easier than using your own counter variable (which still works also).
public static void main(String[] args) {
String[] str1 = {"list item 1", "list item 2", "list item 3", "list item 4"};
List<String> list1 = new ArrayList<String>(Arrays.asList(str1));
ListIterator<String> it = list1.listIterator();
int x = 0;
//The iterator.nextIndex() will return the index for you.
while(it.hasNext()){
int i = it.nextIndex();
System.out.println(it.next() + " is at index" + i);
}
}
This code will go through the list1 list one item at a time and print the item's text, then "is at index" then it will print the index that the iterator found it at. :)
See here.
iterator.nextIndex() would provide index of element that would be returned by subsequent call to next().
Though you already had the answer, thought to add some info.
As you mentioned Collections explicitly, you can't use listIterator to get the index for all types of collections.
List interfaces - ArrayList, LinkedList, Vector and Stack.
Has both iterator() and listIterator()
Set interfaces - HashSet, LinkedHashSet, TreeSet and EnumSet.
Has only iterator()
Map interfaces - HashMap, LinkedHashMap, TreeMap and IdentityHashMap
Has no iterators, but can be iterated using through the keySet() / values() or entrySet() as keySet() and entrySet() returns Set and values() returns Collection.
So its better to use iterators() with continuous increment of a value to get the current index for any collection type.
Related
This question already has answers here:
Collection throws or doesn't throw ConcurrentModificationException based on the contents of the Collection [duplicate]
(5 answers)
Closed 6 years ago.
I have tried the following two scenarios:
ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("1")) {
arrayList.remove(0);
}
}
The first scenario output is :
---->1
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Test.main(Test.java:83)
Probably the ConcurrentModificationException exception is caused because I'm trying to modify the collection while I'm still iterating it.
In the second scenario I changed the if() condition from value.equals("1") to value.equals("2") and the program does not throw any error.
ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
arrayList.remove(0);
}
}
The second scenario output is:
---->1
---->2
In both the scenarios, my program does not reach the 3rd element (Value : 3).
Can you please help me to understand the problem ?
Problem is you are removing element from the list which presend at index 0. Instead of removing from the list use iterator.remove() method. For more info read this.
program code -
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
iterator.remove();
}
}
Why list not returning the last element?
Answer -
you are removing element from the list and you already perform iterator action against same list. At the end iterator.hasnext() method returns false so you are not getting last element.
If you want to see it for demo purpose run below sample codes -
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
arrayList.remove(0);
}
}
System.out.println("ArrayList : "+arrayList);
output -
---->1
---->2
ArrayList : [2, 3]
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
iterator.remove();
}
}
System.out.println("ArrayList : "+arrayList);
output -
---->1
---->2
---->3
ArrayList : [1, 3]
By running two pieces of code in debug mode, I found the following.
1st scenario:
Elements saved from arraylist:
After the remove command has been executed:
The ConcurrentModificationException gets thrown at the following line
String value = (String) iterator.next();
2nd Scenario:
The ArrayList will be the same as the second link.
After printing 2, the control breaks from
while (iterator.hasNext())
as iterator.hasNext() = null. Hence it's safe.
I suppose that you encounter the problem only in the first case because you are trying to remove the element pointed by the iterator. In fact, the second scenario succeeds because you remove the first arraylist element that, at that moment, is not pointed by the iterator.
(p.s. I agree with all the various and future answers that will describe you how to solve your problem by showing fragments of code, I just provided you an explanation of what happens)
The ConcurrentModificationException occurs because you are removing the same element (at index 0) that the current iteration of the loop is reading (the one with value = ”1”). In the second case you don't see the exception because you are removing the element at index 0, but are reading the element at index 1 (the one with value = "2"). You cannot remove an element concurrently while reading it unless you use one of the collections that supports concurrency (see java.util.concurrent package)
You are removing an element (remove(0)) while iterating the list, which "shifts the end of the list" towards left by one. So, the next time you check for iterator.hasNext(), it will return false and the original 3rd element never gets processed.
When you iterate on a Collection, you should remove the element with the iterator :
iterator.remove()
In the second code, here :
if (value.equals("2")) {
arrayList.remove(0);
}
you remove the first element of the list. The list has so a size of 2 elements.
The iterator implementation takes into consideration the size of the list to know if it has next elements or not :
public class ArrayList<E> extends AbstractList<E>
...
private class Itr implements Iterator<E> {
public boolean hasNext() {
return cursor != size;
}
}
Since two elements were iterated and that the list has now a size of 2 because you remove one element of it, the iterator considers that it has not next element to iterate on.
If you use an iterator to remove the current element, you have not this side-effect.
Here is my code. I have an arraylist of visited elements. So I want delete these visited elements from the hashmap and below is code. It gives me concurrentmodification exception.
private static void removeVisitedNodes(ArrayList<String> arrayList) {
// TODO Auto-generated method stub
Iterator<String> it = arrayList.iterator();
String temp;
while(it.hasNext())
{
temp = it.next();
System.out.println("temp is " + temp);
Iterator<Entry<String, ArrayList<String>>> iter = neighbours_reachability_map.entrySet().iterator();
// iterate through the hashmap to remove elements
while (iter.hasNext()) {
Entry<String, ArrayList<String>> entry = iter.next();
if(entry.getValue().contains(temp)){
//System.out.println("Contains it" + entry.getValue().toString());
entry.getValue().remove(temp);
}
}
}
}
I checked up a few other similar questions but they did not help much. Is there a neater way to do this without causing an exception? Thanks in advance for your help.
To remove a element whilst in the middle of iterating, use Iterator.remove().
you can put the elementos you want to delete in another collection object and then, after finished the iteration, delete those elements
Being new to Java, the following code confuses me. I'm trying to do a simple loop based on a list.
List memberships = getMembership(username);
for( Iterator<Integer> single = memberships.iterator(); single.hasNext(); )
{
System.out.println(print_the_current_string_in_list);
}
I have the following questions:
The loop never stops with the above, even though I only have three items in the list. Why is this?
How can I output the current string in the list?
Hopefully your List if of type String and not Integer so it should be
List<String> memberships = getMembership(username);
There are multiple ways to loop over the data for example:
for(String single : memberships) {
System.out.println(single);
}
Another way:
for(int i = 0; i < memberships.size(); i++) {
System.out.println(memberships.get(i));
}
Using the Iterator
for(Iterator<String> iterator = membership.iterator(); iterator.hasNext();) {
System.out.println(iterator.next());
}
Instead of using a for loop you may use an Iterator with a while loop
Iterator<String> iterator = membership.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
Try an advanced for loop, like so:
for(String membership : memberships)
System.out.println(membership);
You can use the foreach statement, which uses the iterator that the list has already implemented.
And you should also specify the type of the elements that the list will contain in the List declaration, like this:
List<String> memberships = getMembership(username);
for( String m : memberships )
{
System.out.println(m);
}
You need to actually iterate over the members with next() method from Iterator:
for (Iterator<Integer> single = memberships.iterator (); single.hasNext (); ) {
Integer next = single.next ();
System.out.println (next);
}
Also, you can use the new for each construct:
for (Integer current : memberships)
System.out.println (current);
You haven't iterated through the list.Use next() method.Thats why its going into an infinite loop.
for( Iterator<Integer> single = memberships.iterator(); single.hasNext();{
System.out.println( single.next());
}
How can I iterate through items of a LinkedHashSet from the last item to the first one?
If you want to continue to use collections, you could use the following:
LinkedHashSet<T> set = ...
LinkedList<T> list = new LinkedList<>(set);
Iterator<T> itr = list.descendingIterator();
while(itr.hasNext()) {
T item = itr.next();
// do something
}
If you're fine with using an array instead, you could take a look at hvgotcodes' answer.
This is another way:
LinkedHashSet<T> set = ...
List<T> list = new ArrayList<>(set);
Collections.reverse(list);
for( T item : list ){
...
}
er, assuming you mean LinkedHashSet...
I would use toArray and just use a reverse for loop.
There might be a better way to do it, but that should work. toArray guarantees any order is preserved
If this set makes any guarantees as to what order its elements are
returned by its iterator, this method must return the elements in the
same order.
Something like
Set<MyType> mySet = new LinkedHashSet();
...
MyType[] asArray = mySet.toArray(new MyType[0]);
for (int i = asArray.length - 1; i>=0; i--){
..
}
If you really meant LinkedHashSet, you could put the elements into an ArrayList and then use the ArrayList's ListIterator.
ListIterator<T> l = new ArrayList<T>(yourLinkedHashList).listIterator();
// ListIterator can iterate in reverse
while(l.hasPrevious()) {
T obj = l.previous();
}
From the javadoc: "This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order)."
So you can simply:
LinkedHashSet<Integer> numbers = new LinkedHashSet<Integer>();
numbers.add(1);
numbers.add(2);
numbers.add(33);
numbers.add(44);
numbers.add(108);
for (Integer i : numbers) {
System.out.println(i);
}
I was working on a code and I came across this. How can I use for-each in the below mentioned code to perform the same as the loop show exactly below (two nested for loops):
String names[3] = {"A","B","C"};
int result[][] = calculate_exchange(calculate_matrix());//function call returns a 3x3 matrix
/*for(int i[]:result){
for(int j:i){
if(j!=0){
System.out.println(names[]);//how do I use the i'th element?
//names[i] gives an error(obviously!!!)
}
}
}*/
for(int r=0;r<3;r++){//this loop works fine
for(int c=0;c<3;c++){
if(result[r][c]!=0){
System.out.println(names[r]+"->"+names[c]+" = "+result[r][c]);
}
}
}
for(int i[]:result) makes i an array, then would it be possible to use for-each in this case?
PS:I have got my code working without using for-each, i am asking this just to satisfy my curiosity.
From the Sun Java Docs:
So when should you use the for-each loop?
Any time you can. It really beautifies your code. Unfortunately, you cannot use it everywhere. Consider, for example, the expurgate method. The program needs access to the iterator in order to remove the current element. The for-each loop hides the iterator, so you cannot call remove. Therefore, the for-each loop is not usable for filtering. Similarly it is not usable for loops where you need to replace elements in a list or array as you traverse it.
In this case you can't do a clean replacement because c is used in the loop. (so you can't eliminate it completely)
You can write
for(int r=0,c;r<3;r++){//this loop works fine
c=0;
for(int[] row: result[r]){
if(row[c]!=0)
System.out.println(names[r]+"->"+names[c]+" = "+row[c]);
c++;
}
}
for (int[] row : result) {
for (int cell : row) {
// do something with the cell
}
}
But since your code needs the index of the row and of the cell in the row, the foreach loop is just not the right tool for the job. Keep your code as is.
You could just use the length of each array rather than hardcoding 3.
You can use iterator in java which act like for each loop
here's an example
// Demonstrate iterators.
import java.util.*;
class IteratorDemo {
public static void main(String args[]) {
// create an array list
ArrayList al = new ArrayList();
// add elements to the array list
al.add("C");
al.add("A");
al.add("E");
al.add("B");
al.add("D");
al.add("F");
// use iterator to display contents of al
System.out.print("Original contents of al: ");
Iterator itr = al.iterator();
while(itr.hasNext()) {
Object element = itr.next();
System.out.print(element + " ");
}
System.out.println();
// modify objects being iterated
ListIterator litr = al.listIterator();
while(litr.hasNext()) {
Object element = litr.next();
litr.set(element + "+");
}
System.out.print("Modified contents of al: ");
itr = al.iterator();
while(itr.hasNext()) {
Object element = itr.next();
System.out.print(element + " ");
}
System.out.println();
// now, display the list backwards
System.out.print("Modified list backwards: ");
while(litr.hasPrevious()) {
Object element = litr.previous();
System.out.print(element + " ");
}
System.out.println();
}
}
Contact if u have any doubt