Java | Implementación de iterador e interfaz iterable

Los iteradores se utilizan en el marco de la colección en Java para recuperar elementos uno por uno. Para obtener más detalles y una introducción relacionada con esto, consulte este enlace .

¿Por qué es necesario implementar la interfaz iterable?

Cada clase que implementa la interfaz Iterable de manera adecuada, se puede usar en el bucle For mejorado (bucle for-each). La necesidad de implementar la interfaz Iterator surge al diseñar estructuras de datos personalizadas.
Ejemplo:

for(Item item: customDataStructure) {
    // do stuff
}

¿Cómo implementar la interfaz iterable?

Para implementar una estructura de datos iterables, necesitamos:

  1. Implemente la interfaz iterable junto con sus métodos en dicha estructura de datos
  2. Cree una clase Iterator que implemente la interfaz Iterator y los métodos correspondientes.

Podemos generalizar el pseudocódigo de la siguiente manera:

class CustomDataStructure implements Iterable<> {
      
    // code for data structure
    public Iterator<> iterator() {
        return new CustomIterator<>(this);
    }
}
class CustomIterator<> implements Iterator<> {
      
    // constructor
    CustomIterator<>(CustomDataStructure obj) {
        // initialize cursor
    }
      
    // Checks if the next element exists
    public boolean hasNext() {
    }
      
    // moves the cursor/iterator to next element
    public T next() {
    }
      
    // Used to remove an element. Implement only if needed
    public void remove() {
        // Default throws UnsupportedOperationException.
    }
}

Nota : la clase Iterator también se puede implementar como una clase interna de la clase de estructura de datos, ya que no se usará en ningún otro lugar.

  1. ¿Cómo funcionan next() y hasNext()?
    Para implementar un iterador, necesitamos un cursor o puntero para realizar un seguimiento de en qué elemento nos encontramos actualmente. Dependiendo de la estructura de datos subyacente, podemos avanzar de un elemento a otro. Esto se hace en el método next() que devuelve el elemento actual y el cursor avanza al siguiente elemento.
    Antes de avanzar el puntero, verificamos si existe el siguiente elemento. es decir, podemos imaginar el código detrás de escena de la siguiente manera:
    While(iterator.hasNext()) { //if next element exists
        next(); // advance the pointer
    }
    
  2. Inicializar el cursor
    La inicialización del cursor depende completamente de la estructura de datos. Por ejemplo, en una lista enlazada, inicializaríamos el cursor en el elemento principal. En una lista de array, inicializaríamos el cursor en el elemento 0.
    Desde el punto de vista de la implementación:
    • Si la clase Iterator se implementa como una clase interna, simplemente podemos usar la palabra clave «esta» (por ejemplo, cursor = CustomDataStructure.this.element) para acceder al elemento deseado
    • Si la clase Iterator se implementa como una clase separada, podemos pasar este objeto de la estructura de datos al constructor de la clase iterator como se muestra en el siguiente ejemplo.

El siguiente programa ilustra el uso de la interfaz iterable:

A continuación se muestra una Lista Vinculada Personalizada que utiliza Genéricos. La lista vinculada consta de objetos de Node que contienen un valor de datos genéricos y un puntero al siguiente Node. La clase proporciona algunos métodos ‘get’ estándar como getHead() y getTail(), y la función Iterator() necesaria, que debe implementarse al implementar la interfaz Iterable.

Luego se crea la clase personalizada necesaria ‘ListIterator’, que implementará la interfaz Iterator, junto con las funcionalidades de hasNext() y next() también se implementarán. Estas dos funciones forman el núcleo de la interfaz Iterable e Iterator.

import java.util.Iterator;
  
// Custom Linked List class using Generics
class List<T> implements Iterable<T> {
    Node<T> head, tail;
      
    // add new Element at tail of the linked list in O(1)
    public void add(T data)
    {
        Node<T> node = new Node<>(data, null);
        if (head == null)
            tail = head = node;
        else {
            tail.setNext(node);
            tail = node;
        }
    }
      
    // return Head
    public Node<T> getHead()
    {
        return head;
    }
      
    // return Tail
    public Node<T> getTail()
    {
        return tail;
    }
      
    // return Iterator instance
    public Iterator<T> iterator()
    {
        return new ListIterator<T>(this);
    }
}
  
class ListIterator<T> implements Iterator<T> {
    Node<T> current;
      
    // initialize pointer to head of the list for iteration
    public ListIterator(List<T> list)
    {
        current = list.getHead();
    }
      
    // returns false if next element does not exist
    public boolean hasNext()
    {
        return current != null;
    }
      
    // return current data and update pointer
    public T next()
    {
        T data = current.getData();
        current = current.getNext();
        return data;
    }
      
    // implement if needed
    public void remove()
    {
        throw new UnsupportedOperationException();
    }
}
  
// Constituent Node of Linked List
class Node<T> {
    T data;
    Node<T> next;
    public Node(T data, Node<T> next)
    {
        this.data = data;
        this.next = next;
    }
      
    // Setter getter methods for Data and Next Pointer
    public void setData(T data)
    {
        this.data = data;
    }
      
    public void setNext(Node<T> next)
    {
        this.next = next;
    }
      
    public T getData()
    {
        return data;
    }
      
    public Node<T> getNext()
    {
        return next;
    }
}
  
// Driver class
class Main {
    public static void main(String[] args)
    {
        // Create Linked List
        List<String> myList = new List<>();
          
        // Add Elements
        myList.add("abc");
        myList.add("mno");
        myList.add("pqr");
        myList.add("xyz");
          
        // Iterate through the list using For Each Loop
        for (String string : myList)
            System.out.println(string);
    }
}
Producción:

abc
mno
pqr
xyz

Publicación traducida automáticamente

Artículo escrito por sejalpawar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *