views:

162

answers:

6

I'm implementing a Graph which holds "Book" objects as its nodes. The nodes are connected if the books share a keyword. The keywords for each book are held in a Vector within the Book class. To do this, I've created 3 classes.

1) Books 2) Vertex 3) Graph

The Vertex class holds the Book object and also has a Vector containing all the other Vertex objects (other books which share a keyword). In the Driver, I create the book, pass it to a Graph which then inserts it into a Vertex and finally the Vertex into a Vector named "bookGraph".

public final class Graph {

private Vector bookGraph = new Vector(); private int bookCounter = 0;

public Graph() {

}

public void addBook(Book bk) { Vertex vtx = new Vertex(bk);

bookGraph.add(vtx); bookCounter++;

System.out.println("Book #1 has " + bookGraph.get(0).getBook().getKeywords().size() + " keywords");

// addAdjVertices();

}

public void showKeywords() {

System.out.println("Book #1 is " + bookGraph.get(0).getBook().getKeywords().size() + " keywords");

}

The information from the books are read from a file in the Driver and inserted into a book object. I'm trying to make sure that this information is read in correctly and properly inserted into the Graph. My problem occurs when trying to get the size of the keyword Vector within the "showKeywords()" method in the Graph class. bookGraph.get(0).getBook().getKeywords().size() returns 0 when the exact same command in the addBook() method returns the correct size. I've implemented accessor methods such as getTitle() or getAuthor() in the Book class and those work correctly within the showKeywords() method. The keyword vector seems to be the only issue within the showKeywords() method. What am I doing wrong here?

Here is my Driver class....

  boolean fileopen = false;
  String title, author, keys;
  long isbn_number;
  Vector<String> keywords = new Vector<String>();
  String filename = "books.txt";
  String[] keywordTokens;
  Scanner fin = null;
  Scanner input = new Scanner (System.in); 
  Graph books = new Graph();

  try {
   fin = new Scanner (new FileReader(filename));
   String fline;

   fileopen = true;

   System.out.println("Reading books.txt...");

   while (fin.hasNextLine()) {

    fline = fin.nextLine();
    title = fline;
    fline = fin.nextLine();
    author = fline;
    fline = fin.nextLine();
    isbn_number = Long.parseLong(fline);
    fline = fin.nextLine();
    keywordTokens = fline.split(",");

    for (int x = 0; x < keywordTokens.length; x++) {
     keywords.add(keywordTokens[x]);
    }

    Book tempBook = new Book(title,author,isbn_number,keywords);
    books.addBook(tempBook);
    keywords.clear();

    if (fin.hasNextLine()) fline = fin.nextLine();


   }

   books.showKeywords();   
   System.out.println("Ready.");
 }
 catch (FileNotFoundException e) {
  System.out.println("FILE NOT FOUND!");
 }
+2  A: 

Looks to me like it should work - there's nothing obviously wrong (like accidentally using static variables). Can you provide a short but complete program which demonstrates the problem? The error is likely to be somewhere else - are you calling setKeywords(new Vector<String>()) somewhere, for example?

Any reason for using Vector rather than the more common ArrayList by the way? I would also suggest that setKeywords(String key) should probably be called addKeyword instead...

EDIT: Okay, now that you've posted the code it's obvious: you're only ever creating a single instance of Vector. You're then reusing that instance for every line, and clearing it at the end.

Just declare your keywords variable inside the loop, create a new instance on every iteration, and don't clear it afterwards.

To make your code as readable as possible (and avoid this sort of thing) I would suggest you declare every variable at the point of first use wherever possible, with the narrowest possible scope.

Jon Skeet
Ah, ArrayList didn't used to be more common. Back when I was a nipper when Java was 1.0 Vector was all we had and we were grateful ;-) I think back then it was called Vector to make C++ migrators a bit happier.
Benj
I've not yet used any instances of the setKeywords() method. No static variables anywhere either. Not sure what the most appropriate way to paste in my driver would be as I'm only allowed 600 characters here.
Vahe
@Vahe: Edit your question instead... but cut the sample code down as much as possible, so it's really short. You may well find that in doing so, you discover the problem yourself.
Jon Skeet
Edited my original post and added the Driver. Thanks.
Vahe
Ahhh. Works perfectly now. Thank you very much.
Vahe
A: 

I think you got lost in your graph of objects :) I suggest to use unit tests to determine how your code should behave and to make sure it actually does behave the way you expect. The tests can build small examples and then check the various getters to see whether they return the correct results.

Aaron Digulla
+1  A: 

Could you try this snippet and check whether the error is still there:

public void test() {
  Vector<String> keywords = new Vector<String>();
  keywords.add("keyword");
  Book bk = new Book("Author", "Title", 12345, keywords);

  Graph bookGraph = new Graph();
  bookGraph.addBook(bk);
  bookGraph.showKeywords();
}
Andreas_D
This works when I insert it into Graph.java. However, attempting the same thing from my Driver class results in the original error.
Vahe
To elaborate, I inserted this snippet into Graph.java. Then called it via books.test(). (books being a Graph object).
Vahe
So now you're sure that the problem is not related to Vector#size and that it is in another part of your application, maybe even inside you Driver class.
Andreas_D
+1  A: 

I am sorry... this should be a comment, but sadly since I just started posting on this site, I don't have enough credits to comment.

I agree with Adnreas_D above, the problem appears to be in your driver. Can you post the code for your driver? It might also help to see the code for Vertex, though I doubt the issue is in there since Andreas_D's test case worked outside the driver.

PaulP1975
Edited my original post to add the driver.
Vahe
Your problem is here: Book tempBook = new Book(title,author,isbn_number,keywords); books.addBook(tempBook); keywords.clear();Your keywords is a vector (e.g. an object) and you pass in a reference to create the tempBook, then you clear the reference... which clears the keywords in tempBook as well. You want to create a new vector each time locally on the stack.
PaulP1975
for those in the know, is there a way to format code in the comments? Vahe, sorry for the bad formatting above...
PaulP1975
A: 

Are you creating more than one Graph in your driver? Post your Driver code - it will help identify the problem.

aldrin
A: 

For what do you need the copy constructor Book(Book)? Perhaps you put copies of the books instead of the books itself into your collection?

mfx