66

I am trying to iterate through a list of keys from a hash table using enumeration however I keep getting a NoSuchElementException at the last key in list?

Hashtable<String, String> vars = new Hashtable<String, String>();

vars.put("POSTCODE","TU1 3ZU");
vars.put("EMAIL","job.blogs@lumesse.com");
vars.put("DOB","02 Mar 1983");

Enumeration<String> e = vars.keys();

while(e.hasMoreElements()){

System.out.println(e.nextElement());
String param = (String) e.nextElement();
}

Console output:

EMAIL
POSTCODE
Exception in thread "main" java.util.NoSuchElementException: Hashtable Enumerator
    at java.util.Hashtable$Enumerator.nextElement(Unknown Source)
    at testscripts.webdrivertest.main(webdrivertest.java:47)

skaffman
  • 381,978
  • 94
  • 789
  • 754
David Cunningham
  • 889
  • 1
  • 11
  • 22

7 Answers7

118

You call nextElement() twice in your loop. This call moves the enumeration pointer forward. You should modify your code like the following:

while (e.hasMoreElements()) {
    String param = e.nextElement();
    System.out.println(param);
}
Pascal Schneider
  • 395
  • 1
  • 4
  • 18
AlexR
  • 109,181
  • 14
  • 116
  • 194
75
for (String key : Collections.list(e))
    System.out.println(key);
weston
  • 51,132
  • 20
  • 132
  • 192
user3162459
  • 783
  • 5
  • 2
  • 29
    Massively inefficient! `Collections.list` creates a new `ArrayList` and copies each value from the enumeration into the new list before returning the list reference. A very big price to pay for cute syntax. – Andy Brown Feb 23 '15 at 15:43
  • 7
    @AndyBrown not if your list is small or not very big. And.. cute syntax helps on making the code more clear. – Aquarius Power Dec 02 '15 at 18:35
  • 1
    a shorter variant is Collections.list(e).forEach(System.out::println); – RoberMP Mar 27 '16 at 19:09
  • 3
    @AndyBrown It's not massively inefficient. It's O(2n) vs O(n), same order of magnitude. And for a big enough list, it's possible that with parallel streams and the right hardware, it will be faster to iterate through the list. – anataliocs Jan 11 '17 at 16:05
  • @anataliocs with Collections.list(e) using an ArrayList with initial default size of 10 internally there may me a considerable number of array allocations and copies involved. As ArrayList grows by half it's current size if it's over capacity, an enumeration with 1000 elements would create no less than 13 arrays (sizes 10, 15, 22, 33, 49, 73, 109, 163, 244, 366, 549, 823, 1234) and copy 12 of them – sfussenegger Jun 28 '18 at 13:43
10

Every time you call e.nextElement() you take the next object from the iterator. You have to check e.hasMoreElement() between each call.


Example:

while(e.hasMoreElements()){
    String param = e.nextElement();
    System.out.println(param);
}
dacwe
  • 41,465
  • 11
  • 110
  • 135
4

You are calling nextElement twice. Refactor like this:

while(e.hasMoreElements()){


String param = (String) e.nextElement();
System.out.println(param);
}
Heisenbug
  • 37,414
  • 27
  • 126
  • 181
3

You're calling e.nextElement() twice inside your loop when you're only guaranteed that you can call it once without an exception. Rewrite the loop like so:

while(e.hasMoreElements()){
  String param = e.nextElement();
  System.out.println(param);
}
Edward Dale
  • 28,070
  • 11
  • 84
  • 128
3

You're calling nextElement twice in the loop. You should call it only once, else it moves ahead twice:

while(e.hasMoreElements()){
    String s = e.nextElement();
    System.out.println(s);
}
JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
1

Each time you do e.nextElement() you skip one. So you skip two elements in each iteration of your loop.

cadrian
  • 7,095
  • 2
  • 30
  • 41