Search code examples
javagenericsiteratorraw-types

Declaration of generic Iterators


I am programming a class called graph and I am representing the directed graph by a Hashmap. I want to create a method that prints out the whole graph in the following way:

key1: value13, valeue17, ..
key2: value21, ...

where value13 is the value of the node3 to which node1(key1) is pointing to. So, for something like 1->2->3, and 2 pointing also to 4 I need:

1: 2
2: 3,4

my code looks like this:

public class Graph<T>{
  Map<Node<T>, List<Node<T>>> graph;

  //constructors and methods

  void printGraph(){
    System.out.println(graph.keySet().iterator().next().value); // is printing 7
    Iterator itKey = graph.keySet().iterator();
    System.out.println(itKey.next()); // printing Graph$Node@15db9742
    System.out.println(itKey.next().value); //error
    while(itKey.hasNext()){
    //code
  }

  public static void main(String[] args){
    Graph<Integer> graph = new Graph<>();
    Node<Integer> n1 = new Node<>(7);
    Node<Integer> n2 = new Node<>(2);
    graph.connect(n1, n2);
    graph.printGraph();
  }
}

my problem arises in the method printGraph(), where I define an Iterator. What I want to do is create an Iterator on the set of keys, and for every key then create an iterator that will print all the values. As you can see, if I try to print System.out.println(graph.keySet().iterator().next().value); I get a 7, which makes sense because it is the value of my first key in my keySet(). If I the do it on an other way, initializing the iterator, Iterator itKey = graph.keySet().iterator();, this is an iterator pointing on a Node:

System.out.println(itKey.next()); // printing Graph$Node@15db9742

Although, if I try to print its value:

System.out.println(itKey.next().value); //error

I get the following error:

error: cannot find symbol
    System.out.println(itKey.next().value);
                                   ^
  symbol:   variable value
  location: class Object
1 error

shouldn't this be the same thing? Why is the error arising?


Solution

  • That is a compilation error, because your Iterator itKey has a raw type; so calls to itKey.next() will return an Object. You want to specify the right type for your iterator, so that iterator.next() has return type Node.

    In your code, just change the type for the itKey variable

      void printGraph() {
        System.out.println(graph.keySet().iterator().next().value);
        // use the non-raw type here
        Iterator<Node<T>> itKey = graph.keySet().iterator();
        System.out.println(itKey.next());
        System.out.println(itKey.next().value); 
        while (itKey.hasNext()) {
          // code
        }
      }
    

    The line System.out.println(graph.keySet().iterator().next().value); compiles, because no type information is lost. Looking at the types involved:

    • the graph variable has type Map<Node<T>, List<Node<T>>>
    • graph.keySet() has type Set<Node<T>>
    • graph.keySet().iterator() has type Iterator<Node<T>>
    • graph.keySet().iterator().next() has type Node<T>

    and since the type for the last next() is a Node, we can get its value.