1

I want to implement the Iterable interface in my own linked list for a foreach method with Consumer, but I can't figure out how to make the next() method return a Node instead of the generic type. I know usually you would want iterator to be of the type of the data stored inside the Node, but I want it to be the Node itself for more flexibility. I am fairly new to generics and Java in general.

This is the relevant part of my class. Furthermore, there are some add and remove methods that are not really of interest here.

import java.util.Iterator;

class OwnList<Type> implements Iterable<T>{

    class Node{
        Type data;
        Node next;

        public Node(Type data, Node next){
            this.data = data;
            this.next = next;
        }
    }

    Node head;

    @Override
    public <T> Iterator<T> iterator(){
        Iterator<T> iterator = new Iterator<T>(){
            private Node index = head;

            @Override
            public boolean hasNext(){
                return index.next == null ? false : true;
            }

            @Override
            public T next(){
                return index = index.next;
            }

            @Override
            public void remove(){

            }
        };
        return iterator;
    }

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • Does this answer your question? [Implementing custom Iterator on a LinkedList](https://stackoverflow.com/questions/29204945/implementing-custom-iterator-on-a-linkedlist) – Oliver Nov 28 '21 at 16:40
  • If you want it iterate over `Node`, then you should implement `Iterable`, and return an `Iterator`. – Mark Rotteveel Nov 28 '21 at 17:29

1 Answers1

0

I separated it out into 2 classes, as opposed to having it all smushed together into one.

Node.java

public class Node<T>
{

   private T data;
   private Node<T> next;

   public Node(T data, Node<T> next)
   {
   
      this.data = data;
      this.next = next;
   
   }
   
   public Node<T> next()
   {
   
      return this.next;
   
   }
   
}

NodeList.java

import java.util.Iterator;

public class NodeList<T> implements Iterable<Node<T>>{

   private Node<T> head;

   @Override
   public Iterator<Node<T>> iterator()
   {
      
      return 
         new Iterator<Node<T>>()
         {
         
            private Node<T> index = head;
         
            @Override
            public boolean hasNext()
            {
               return index.next() == null ? false : true;
            }
         
            @Override
            public Node<T> next()
            {
               return index = index.next();
            }
         
            @Override
            public void remove()
            {
            
            }
         };
   
   }
   
}

EDIT - found another way of rewriting Node.java. The plus side is that it is a lot less code. The only catch is that your data is now shallowly immutable. Also, this only works for Java 14 or greater.

Node.java - reworked

import java.util.Iterator;

public record Node<T>(T data, Node<T> next)
{

   public Node(Node<T> node)
   {
   
      this(node.data, node.next);
   
   }

}

Also, you don't need to make any changes to NodeList.java - you can just switch out Node.java to use this immutable version.

davidalayachew
  • 1,279
  • 1
  • 11
  • 22