简体   繁体   中英

Java Iterator infinite loop iterates only the 1st item in hashmap

I am executing a database query, and as result I get a HashMap. I want to iterate through all the results, but I infinitely add the first item from the result to the arraylist.

QueryResult result=engine.query(query,params);

while(result.iterator().hasNext()) {
    HashMap res= (HashMap)result.iterator().next();
    Node node=(Node)res.get("n");
    results.add(new BusyProfile(node));
}

How to iterate through each object and why do I have infinite loop? Thanks!

Everytime you call result.iterator() , a new Iterator is created, pointing to the first item.

So create it before your loop:

Iterator<?> it = result.iterator();
while (it.hasNext()) {
  HashMap res = (HashMap)it.next();
  //...
}

You are overwriting your iterator! When result.iterator() is called, you create your iterator but on each iteration, it's creating a new one and it continues to point to the beginning - causing the infinite loop.

What you need to do in this case is save the iterator and then use it to move through the collection.

QueryResult result = engine.query(query,params);

//Save iterator
Iterator i = result.iterator();

while(i.hasNext()) {
    HashMap res = (HashMap)i.next();
    Node node   = (Node)res.get("n");
    results.add(new BusyProfile(node));
}

Before you can access a collection through an iterator, you must obtain one. Each of the collection classes provides an iterator( ) method that returns an iterator to the start of the collection. By using this iterator object, you can access each element in the collection, one element at a time.

In general, to use an iterator to cycle through the contents of a collection, follow these steps −

Obtain an iterator to the start of the collection by calling the collection's iterator( ) method.

Set up a loop that makes a call to hasNext( ). Have the loop iterate as long as hasNext( ) returns true.

Within the loop, obtain each element by calling next( ).

There is a quick tutorial here: https://www.tutorialspoint.com/java/java_using_iterator.htm

All answers posted before mine explained that result.iterator() will instantiate a new iterator each time it is invoked.
And it makes not sense to create an iterator during each iteration for the same iterator that you are iterating with : while(result.iterator().hasNext()) { .
It is right.

Beyond this misuse of the Iterator , you should read the javadoc of the class you are using. It may often help you to create a more effective code.
According to the javadoc of org.neo4j.ogm.session.result.QueryResult , the QueryResult class implements the Iterable interface in this way Iterable<Map<String,Object>> .

So instead of doing thing more complicated than required, just use an enhanced for .
It would produce a shorter and more readable code.
Besides, using the more restricted scope for a variable is better as it prevents to use it unsuitably.
With the enhanced for, you don't need any longer to declare the iterator before the loop.
It will be used in the compiled class (as enhanced for uses under the hood an iterator) but it will be restricted to the scope of the loop.

So you should really consider this way :

QueryResult result = engine.query(query,params);

for (Map<String,Object> currentMap : result) {
   Node node = (Node) currentMap.get("n");
   results.add(new BusyProfile(node));
}

您应该调用iterator()方法一次,然后存储(并使用)返回的值。

Reuse the Iterator

Iterator i = result.iterator();
if(i.hasNext()) {
    HashMap res= (HashMap)i.next();
    Node node=(Node)res.get("n");
    results.add(new BusyProfile(node));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM