views:

45

answers:

1

Hi, I'm parsing this JSON string with the libs in org.json and I can't understand why I get the output below into the log.

ArrayList<String> al = new ArrayList<String>();
JSONObject demo = new JSONObject("{\"00408C88A2E6\":{\"id\":\"00408C88A2E6\",\"name\":\"Lab\"},\"00408C91188B\":{\"id\":\"00408C91188B\",\"name\":\"Lab1\"},\"00408C944B99\":{\"id\":\"00408C944B99\",\"name\":\"Lato1\"},\"00408C944BA0\":{\"id\":\"00408C944BA0\",\"name\":\"Lato\"}}");
Iterator<String> iterator =  demo.keys();
while (iterator.hasNext() ){    
  al.add((String)iterator.next());
  Log.i(LOG_TAG, "size al into while " + al.size());
  Log.i(LOG_TAG, "MAC " + iterator.next() + " for the user " + userId);
} 

Log output

07-12 08:55:34.056: INFO/parse(285): size al into while 1
07-12 08:55:34.056: INFO/parse(285): MAC 00408C91188B for the user nweb
07-12 08:55:34.066: INFO/parse(285): size al into while 2
07-12 08:55:34.066: INFO/parse(285): MAC 00408C944B99 for the user nweb
07-12 08:55:34.066: INFO/parse(285): size al 2

Should not have 4 elements in my ArrayList? Thank you

+5  A: 

You called iterator.next() twice in the body of the loop. Each time you do, the iterator advances forward.

You may want to call it once in the body and store it in a local variable.

String next = iterator.next();
al.add(next);
Log.i(LOG_TAG, "MAC " + next + " for the user " + userId);

Note that Iterator<E> defines E next(), so you don't need the cast to String in this case.


Another illustrative example

Here's an example from Java Language Guide/For-each loop:

Here is a common mistake people make when they are trying to do nested iteration over two collections:

List suits = ...;
List ranks = ...;
List sortedDeck = new ArrayList();

// BROKEN - throws NoSuchElementException!
for (Iterator i = suits.iterator(); i.hasNext(); )
    for (Iterator j = ranks.iterator(); j.hasNext(); )
        sortedDeck.add(new Card(i.next(), j.next()));

Can you spot the bug? Don't feel bad if you can't. Many expert programmers have made this mistake at one time or another. The problem is that the next method is being called too many times on the “outer” collection (suits). It is being called in the inner loop for both the outer and inner collections, which is wrong. In order to fix it, you have to add a variable in the scope of the outer loop to hold the suit:

// Fixed, though a bit ugly
for (Iterator i = suits.iterator(); i.hasNext(); ) {
    Suit suit = (Suit) i.next();
    for (Iterator j = ranks.iterator(); j.hasNext(); )
        sortedDeck.add(new Card(suit, j.next()));
}

So what does all this have to do with the for-each construct? It is tailor-made for nested iteration! Feast your eyes:

for (Suit suit : suits)
   for (Rank rank : ranks)
       sortedDeck.add(new Card(suit, rank));

Had JSONObject.keys() been an Iterable instead of Iterator, then for-each is the best solution in your case. If you think the improvement in readability is worth it, you can e.g. add the keys into a Collection<String>, which is an Iterable.

Related questions

polygenelubricants