2

I am inputting an adjacency list for a graph. There are three columns of data (vertex, destination, edge) separated by a single space. Here is my implementation so far:

         FileStream in = new FileStream("input1.txt");
         Scanner s = new Scanner(in);

         String buffer;
         String [] line = null;
        while (s.hasNext()) 
        {       
            buffer = s.nextLine();
            line = buffer.split("\\s+");     
            g.add(line[0]);
            System.out.println("Added vertex " + line[0] + ".");
            g.addEdge(line[0], line[1], Integer.parseInt(line[2]));
            System.out.println("Added edge from " + line[0] + " to " + line[1] + " with a weight of " + Integer.parseInt(line[2]) + ".");                  
         }

         System.out.println("Size of graph = " + g.size());

Here is the output:

Added vertex a.
Added edge from a to b with a weight of 9.
Exception in thread "main" java.lang.NullPointerException
    at structure5.GraphListDirected.addEdge(GraphListDirected.java:93)
    at Driver.main(Driver.java:28)

I was under the impression that

 line = buffer.split("\\s+");

would return a 2 dimensional array of Strings to the variable line. It seemed to work the first time but not the second. Any thoughts?

I would also like some feedback on my implementation of this problem. Is there a better way? Anything to help out a novice! :)

EDIT:

I tried this implementation earlier today and was unsuccessful. I did it again here:

FileStream in = new FileStream("input1.txt");
             Scanner s = new Scanner(in).useDelimiter("\\s+");

            while (s.hasNext()) 
            {       
                Scanner line = new Scanner(s.nextLine());
                String vertex = line.next();
                String destination = line.next();
                int weight = line.nextInt();     
                g.add(vertex);
                System.out.println("Added vertex " + vertex + ".");
                g.addEdge(vertex, destination, weight);
                System.out.println("Added edge from " + vertex + " to " + destination + " with a weight of " + weight + ".");                  
             }

             System.out.println("Size of graph = " + g.size()); 

Output:

Added vertex a.
Exception in thread "main" java.lang.NullPointerException
    at structure5.GraphListDirected.addEdge(GraphListDirected.java:93)
    at Driver.main(Driver.java:22)

Edit2:

Here is the addEdge function. This is not my own implementation I am using it to save the time of feebly writing my own at this beginning stage...

package structure5;
import java.util.Iterator;


abstract public class GraphList<V,E> extends AbstractStructure<V> implements Graph<V,E>
{
    protected Map<V,GraphListVertex<V,E>> dict; // label -> vertex

    protected boolean directed; // is graph directed?


    protected GraphList(boolean dir)
    {
        dict = new Hashtable<V,GraphListVertex<V,E>>();
        directed = dir;
    }

    public void add(V label)
    {
        if (dict.containsKey(label)) return; // vertex exists
        GraphListVertex<V,E> v = new GraphListVertex<V,E>(label);
        dict.put(label,v);
    }


    abstract public void addEdge(V v1, V v2, E label);
}

Graph.java:

package structure5;
import java.util.Iterator;

public interface Graph<V,E> extends Structure<V>
{
    public void add(V label);


    public void addEdge(V vtx1, V vtx2, E label);
}

Note: I am leaving out the rest of the methods that don't pertain to the program

Edit3: Here is GraphListDirected.java

public class GraphListDirected<V,E> extends GraphList<V,E>
{
    public GraphListDirected()
    {
        super(true);
    }
    public void addEdge(V vLabel1, V vLabel2, E label)
    {
        GraphListVertex<V,E> v1 = dict.get(vLabel1);
        GraphListVertex<V,E> v2 = dict.get(vLabel2);
        Edge<V,E> e = new Edge<V,E>(v1.label(), v2.label(), label, true);   //Line 93
        v1.addEdge(e);
    }
3
  • There is not enough information to suggest why you get NullPointerException. Can you attach addEdge, marking line 93? Commented May 25, 2010 at 4:38
  • we need to see line 93 of GraphListDirected.java, the addEdge method. Also attach add for completeness. The I/O part looks okay. Commented May 25, 2010 at 4:54
  • we're getting closer, but we need GraphListDirected.java, with addEdge (and possible add), with line 93 clearly marked. The addEdge you've given above is abstract and belongs to GraphList, a different class. Commented May 25, 2010 at 5:23

2 Answers 2

2

String.split returns a String[], a one-dimensional array, never a two dimensional array. You can, of course, further split a String that was the result of a split (and so on).

Having said that, since you're already using Scanner, you should never need to use split and Integer.parseInt etc. Just create another Scanner to scan s.nextLine().

Scanner line = new Scanner(s.nextLine());
String from = line.next();
String to = line.next();
int weight = line.nextInt();

I'm not sure what caused the NullPointerException, although we know from your output that at least one edge was successfully added.

API links


On multiple Scanner

The little A-ha!! moment here is the realization that just as you can split on the result of a previous split, you can create a Scanner to scan strings returned from another Scanner.

    String inputText =
        "Line1 a b\n" +
        "Line2 d e f\n" +
        "Line3";
    Scanner input = new Scanner(inputText);
    while (input.hasNext()) {
        Scanner line = new Scanner(input.nextLine());
        System.out.println("[" + line.next() + "]");
        while (line.hasNext()) {
            System.out.println("  " + line.next());
        }
    }

The above snippet prints:

[Line1]
  a
  b
[Line2]
  d
  e
  f
[Line3]

This is just a simple example, but you can see the value of this technique when each line is more complex, e.g. when it contains numbers and regex patterns.


On the NullPointerException

You need to add both the starting and ending vertices, because of the way addEdge is implemented.

            Scanner line = new Scanner(s.nextLine());
            String vertex = line.next();
            String destination = line.next();
            int weight = line.nextInt();     
            g.add(vertex);
            g.add(destination); // <--- ADD THIS LINE!!
            g.addEdge(vertex, destination, weight);

This should fix the NullPointerException.

Hopefully the process of finding this bug has been educational: it took several revisions to the question to gather the relevant information, but finally the culprit of the error has been identified.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for you patience! Everything seems to working fine now. I guess the hardest errors to figure it out is the error in your own logic :D
0

As polygenelubricants mentioned, split() returns String[], not String[][].

Note that split() will recompile the regex pattern on every loop iteration. If your input is small, this won't matter, but if your input is large (maybe thousands of iterations), you would be better off using a second Scanner inside the loop, or using a Pattern that's compiled outside the loop.

To get to the bottom of the NullPointerException, I'd suggest using a debugger (like the one included in Eclipse) and setting a breakpoint at line 93 of GraphListDirected.java (the line reported in the stacktrace). Each time the breakpiont pauses your program at that line, double-check all your values to make sure they are what you would expect to see.

1 Comment

He is using nextLine(). That should do what he wants.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.