Solucione el error NoSuchElementException en Java

Mohammad Irfan 12 octubre 2023
  1. NoSuchElementException al usar Iterator en Java
  2. NoSuchElementException al usar la enumeración en Java
  3. NoSuchElementException al usar StringTokenizer en Java
  4. NoSuchElementException al usar la clase de escáner en Java
Solucione el error NoSuchElementException en Java

Una excepción es un evento que ocurre durante la ejecución de un programa. El flujo normal del programa se ve afectado cuando ocurre una excepción y el programa finaliza de manera anormal. Este tutorial discutirá java.util.NoSuchElementException y cómo manejarlo en Java.

La NoSuchElementException se hereda de la clase RuntimeException, lo que significa que es una excepción sin marcar. El compilador no maneja las excepciones no verificadas, ya que ocurren durante el tiempo de ejecución.

La NoSuchElementException es lanzada por la clase Scanner, la interfaz Iterator, la interfaz Enumerator y la clase StringTokenizer. Estas clases tienen métodos de acceso para obtener el siguiente elemento de un iterable. Lanzan NoSuchElementException si el iterable está vacío o ha alcanzado el límite máximo.

Veamos cómo las diferentes clases lanzan NoSuchElementException.

NoSuchElementException al usar Iterator en Java

La interfaz Iterator tiene un método llamado next() que se utiliza para acceder al siguiente elemento de la iteración. Si no hay ningún elemento en la colección, se lanza NoSuchElementException. Veremos algunos ejemplos.

Intentando iterar un HashMap sin elementos:

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    // creating a hashmap with no element
    HashMap<String, Integer> h1 = new HashMap<>();
    // creating an iterator object
    Iterator i = h1.keySet().iterator();
    // trying to access element
    i.next();
  }
}

Producción :

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1599)
    at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1620)
    at MyClass.main(MyClass.java:9)

El método next() lanza una excepción porque el HashMap está vacío. Podemos usar el método hasNext() para evitar esta excepción; devuelve verdadero si el iterable tiene más elementos.

Deberíamos usar el método next() solo si hasNext() devuelve True, para evitar tales excepciones. Vea el ejemplo a continuación.

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    // creating a hashmap with no element
    HashMap<String, Integer> h1 = new HashMap<>();
    // creating an iterator object
    Iterator i = h1.keySet().iterator();
    // trying to access element
    while (i.hasNext()) {
      i.next();
    }
  }
}

Este código no arroja ninguna excepción. Tomemos un ejemplo con algunos elementos en el HashMap e iteremos los elementos.

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    // creating a hashmap
    HashMap<String, Integer> h1 = new HashMap<>();
    h1.put("one", 1);
    h1.put("two", 2);
    // creating an iterator object
    Iterator i = h1.keySet().iterator();
    // trying to access element
    while (i.hasNext()) {
      System.out.println(i.next());
    }
  }
}

Producción :

one
two

Sin el método hasNext(), este código habría generado una excepción, pero funciona bien.

NoSuchElementException al usar la enumeración en Java

En Java, Enumeration tiene un método llamado nextElement() que devuelve el siguiente elemento de la enumeración. Si no hay ningún elemento para devolver, lanza una NoSuchElementException.

Mire el ejemplo a continuación donde estamos creando una enumeración a partir de una lista.

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    ArrayList<String> animals = new ArrayList<>();
    animals.add(new String("elephant"));
    // creating enumeration object
    Enumeration en = Collections.enumeration(animals);
    System.out.println(en.nextElement()); // gets "elephant"
    System.out.println(en.nextElement()); // throws exception
  }
}

Producción :

elephant

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:970)
    at java.base/java.util.Collections$3.nextElement(Collections.java:5440)
    at MyClass.main(MyClass.java:9)

El hasElement() arroja una excepción después de devolver el primer elemento porque no quedan elementos en ArrayList para acceder. Podemos usar el método hasMoreElements() para evitar esta situación.

Este método devuelve verdadero si hay más elementos en la enumeración para proporcionar; de lo contrario, devuelve falso. Podemos llamar al método nextElement() solo si hay más elementos en la enumeración.

Mira el ejemplo de abajo:

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    ArrayList<String> animals = new ArrayList<>();
    animals.add(new String("elephant"));
    // creating enumeration object
    Enumeration en = Collections.enumeration(animals);
    while (en.hasMoreElements()) {
      System.out.println(en.nextElement()); // gets "elephant"
    }
  }
}

Producción :

elephant

NoSuchElementException al usar StringTokenizer en Java

En Java, la clase StringTokenizer proporciona dos métodos, nextToken() y nextElement(). El método nextToken() devuelve el siguiente token (tipo de cadena) del tokenizador de cadenas, mientras que el método nextElement es como nexttoken() excepto que devuelve un tipo de objeto en lugar de una cadena. Ambos métodos lanzan la NoSuchElementException.

Vea el ejemplo a continuación.

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    String s = "I Love Delft";
    StringTokenizer st = new StringTokenizer(s);
    System.out.println(st.nextToken()); // gets I
    System.out.println(st.nextToken()); // gets Love
    System.out.println(st.nextToken()); // gets Delft
    System.out.println(st.nextToken()); // Throws exception
  }
}

Producción :

I
Love
Delft

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.StringTokenizer.nextToken(StringTokenizer.java:347)
    at MyClass.main(MyClass.java:9)

Podemos evitar la excepción usando el método hasMoreTokens() y hasMoreElements(). Ambos métodos devuelven verdadero si hay más tokens disponibles en la cadena del tokenizador. Deberíamos llamar al método nextToken() solo si el método hasMoreTokens() devuelve True.

Vea el ejemplo a continuación:

import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    String s = "I Love Delft";
    StringTokenizer st = new StringTokenizer(s);
    while (st.hasMoreTokens()) {
      System.out.println(st.nextToken());
    }
  }
}

Producción :

I
Love
Delft

NoSuchElementException al usar la clase de escáner en Java

La clase Scanner en Java proporciona varios métodos de utilidad como next(), nextInt(), etc. Mientras se trabaja con estos métodos, pueden lanzar la excepción NoSuchElementException. Los discutiremos aquí.

  1. Suponga que tiene dos objetos de escáner accediendo a la entrada estándar. Si cierra uno de ellos y llama a un método usando el otro, lanza la NoSuchElementException. Vea el ejemplo a continuación.
import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    String s = "I Love Delft";
    Scanner s1 = new Scanner(System.in);
    Scanner s2 = new Scanner(System.in);
    s1.close();
    s2.next();
  }
}

Producción :

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.Scanner.throwFor(Scanner.java:937)
    at java.base/java.util.Scanner.next(Scanner.java:1478)
    at MyClass.main(MyClass.java:8)

Cuando cerramos el primer Scanner, cierra el InputStream subyacente; por lo tanto, el segundo Scanner no puede leer desde el mismo InputStream y lanza una NoSuchElementException. La solución es usar un objeto de escáner para leer la entrada System.in.

  1. Suponga que está leyendo una cadena o un archivo usando el objeto de escáner. Si no queda ninguna línea para leer, se muestra una excepción. Vea el ejemplo a continuación.
import java.util.*;
public class MyClass {
  public static void main(String args[]) {
    String s = "I Love Delft";
    Scanner s1 = new Scanner(s);
    System.out.println(s1.nextLine());
    System.out.println(s1.nextLine());
  }
}

Producción :

I Love Delft

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
    at MyClass.main(MyClass.java:7)

Para resolver este problema, usamos el método hasNextLine() que devuelve un valor booleano. Mira el ejemplo.

import java.util.*;
public class Main {
  public static void main(String args[]) {
    String s = "I Love Delft";
    Scanner s1 = new Scanner(s);
    while (s1.hasNextLine()) {
      System.out.println(s1.nextLine());
    }
  }
}

Producción :

I Love Delft

Artículo relacionado - Java Error