Resolved Search and display ArrayList stored in a hashtable

nickbtheitguy

Member
Joined
Feb 21, 2009
Messages
6
Programming Experience
Beginner
I am new to VB.net and I am trying to work out an exercise from a book I am reading on VB. Basically I am storing some book information in a hashtable using a class called Book to store the book information. I am trying to work out my Search and Display All procedures. My Search will work for the first value in my arraylist but not for any other values. I even added the ISBN to my book class to try and use this as a search point. The ISBN is used to pull the item from the hashtable as well.

In the main code I am having problems with the ButtonSearch and ButtonAll. Any suggestions would be great.

I have attached what my form looks like.

Main Code
VB.NET:
Public Class FormMain
    Private bookTable As Hashtable = New Hashtable
    Private bookArray As New ArrayList


    Private Sub clearTextBoxes()
        TextBoxISBN.Text = String.Empty
        TextBoxTitle.Text = String.Empty
        TextBoxYear.Text = String.Empty
        TextBoxAuthor.Text = String.Empty
    End Sub

    Private Sub ButtonAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAdd.Click
        Dim aBook As New Book(TextBoxISBN.Text, TextBoxTitle.Text, TextBoxYear.Text, TextBoxAuthor.Text)

        bookArray.Add(aBook.ISBN)
        bookArray.Add(aBook.Title)
        bookArray.Add(aBook.Year)
        bookArray.Add(aBook.Author)

        bookTable.Add(aBook.ISBN, bookArray)

        MessageBox.Show(aBook.ToString, "Added")

        clearTextBoxes()

    End Sub

    Private Sub ButtonSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSearch.Click
        Dim foundBook As Object = bookTable.Item(TextBoxISBN.Text)

        If Not foundBook Is Nothing Then

            Try
                Dim searchArray As Integer
                Dim searchOutput As String
                searchArray = 0
                searchArray = bookArray.BinarySearch(TextBoxISBN.Text, New CaseInsensitiveComparer())


                If searchArray > 0 Then
                    'searchOutput = bookArray(searchArray - 1)
                    MessageBox.Show("Found at " & searchArray)
                Else
                    MessageBox.Show("Not Found")
                End If

            Catch ex As Exception
                MessageBox.Show("Book not found", "Search")
            End Try

        End If

        clearTextBoxes()
    End Sub

    Private Sub ButtonRemove_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRemove.Click
        Dim foundBook As Object = bookTable.Item(TextBoxISBN.Text)

        If Not foundBook Is Nothing Then
            bookTable.Remove(TextBoxISBN.Text)
            MessageBox.Show(foundBook.ToString, "Remove")
        Else
            MessageBox.Show("Book not found", "Remove")
        End If
        clearTextBoxes()
    End Sub


    Private Sub ButtonAll_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonAll.Click
        Dim element As DictionaryEntry
        Dim output As String = Nothing

        For Each element In bookTable
            output &= element.Key & ControlChars.Tab & element.Value + vbCrLf

        Next
        MessageBox.Show(output, "Books")
    End Sub

    Private Sub ButtonExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonExit.Click
        Me.Close()

    End Sub
End Class

Book.vb Class
VB.NET:
Public Class Book

    ' instance variables
    Private _ISBN As String
    Private _title As String
    Private _year As String
    Private _author As String

    Public Sub New(ByVal myISBN As String, ByVal myTitle As String, ByVal myYear As String, ByVal myAuthor As String)
        _ISBN = myISBN
        _title = myTitle
        _year = myYear
        _author = myAuthor
    End Sub

    Public Property ISBN() As String
        Get
            Return _ISBN
        End Get
        Set(ByVal value As String)
            _ISBN = value
        End Set
    End Property

    Public Property Title() As String
        Get
            Return _title
        End Get
        Set(ByVal value As String)
            _title = value
        End Set
    End Property

    Public Property Year() As String
        Get
            Return _year
        End Get
        Set(ByVal value As String)
            _year = value
        End Set
    End Property

    Public Property Author() As String
        Get
            Return _author
        End Get
        Set(ByVal value As String)
            _author = value
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return _ISBN & " " & _title & " " & _year & " " & _author
    End Function
End Class
 

Attachments

  • book.jpg
    book.jpg
    16.7 KB · Views: 32
Last edited:
That's a very full and clear post... until this bit:
I am having problems with the ButtonSearch and ButtonAll.
Would you care to elaborate on these problems? What's happening that shouldn't? What's not happening that should?
 
Well I haven't even touched the ButtonAll yet. I figured I should get the search to work first. Then I can focus on the ButtonAll. Here is what I get with my current search setup. I can enter some test data and if I search for the ISBN and it seems to go straight to the MessageBox.Show("Book not found", "Search"). So I am not doing something right with the BinarySearch of the array out of the hashtable.

I've changed my Search Code. I had made some changes to test with and didn't change it back. At some point I was getting the first result in my array but now I'm not even getting that.

VB.NET:
    Private Sub ButtonSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSearch.Click
        Dim foundBook As Object = bookTable.Item(TextBoxISBN.Text)

        If Not foundBook Is Nothing Then


            Dim searchArray As Integer
            Dim searchOutput As String
            searchArray = 0
            searchArray = bookTable.Item(bookArray.BinarySearch(TextBoxISBN.Text, New CaseInsensitiveComparer()))


            If searchArray > 0 Then
                searchOutput = bookArray(searchArray)
                MessageBox.Show(searchOutput)
            End If

            MessageBox.Show("Book not found", "Search")

        End If

        clearTextBoxes()
    End Sub
 
Your first problem is that you've got a message inside your If block that says that no book was found when you'll only enter that If block if a book WAS found. You obviously need an If block AND an Else block, for if the book IS found and if the book is NOT found.

Second, I don't really get any of that inside your If block. What's the binary search for at all? You've got the ArrayList that corresponds to the ISBN and you know for a fact that it has four items in it because YOU put them there. You know for a fact that the secpond item is the title so, if that's what you're after, then just grab it.

Finally, if you're using VB 2008 then you really shouldn't ever be using Hashtables and ArrayLists at all. You should be using generic Dictionaries and generic Lists, so you're not getting Object references that you have to cast. Also, you've defined a class to represent a book and yet you're not using it. You're putting ArrayLists into your Hashtable instead of creating Book instances.
 
Thanks for pointing out the messagebox. I had been looking at the code so long that I didn't even notice that.

I was trying to use the binary search because I can't seem to put this together in my mind on what it is I need to do. Right now the program creates a hash key for the ISBN and then inserts the arraylist into the value field. Should the arraylist in the value field be a new arraylist for each book? Right now it seems that all of the books are in the same arraylist. So what I am struggling with is getting the book information that corresponds with the ISBN out of the array on my search. The binary search seemed to be the thing to do. I'm not really sure what you mean by "just grab" what I need.

The array has book objects in it. When I populate the arraylist in the Add section I am adding the aBook.ISBN, aBook.Title, aBook.Year, aBook.Author. Thanks for the information about if I am using 2008. The section that I am reading in this book is about Arrays, Collections, and Generics. The exercise is specifically about hashtables.
 
Absolutely each book should have a new ArrayList. I didn't actually notice that but if you only create one ArrayList then it can only contain one set of data. You just keep changing the data it contains and adding it to the collection over and over. Consider this. If I want to write a list of people to invite to a party and I add your name to it 10 times, do you magically become 10 people? Of course not. You're just one person added to the list 10 times. If the first person on that list changes the colour of their shirt, what happens to the other 9? They all change too, don't they? Of course they do, because they are all the same person.

So, you should get rid of your ArrayList variable at the class level. That's not needed or wanted. The steps are thus:

1. Create a new ArrayList and populate it with the data for a book.
2. Add that ArrayList to the Hashtable with its ISBN as key.

3. Specify an ISBN to get the corresponding ArrayList from the Hashtable.
4. Get the book data from the items of that ArrayList.
 
Here is where I get stuck. Just for testing sake, instead of putting the array into the hashtable I just put the aBook.Title in and then tried my search with the following code:

VB.NET:
    Private Sub ButtonSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSearch.Click
        Dim foundBook As Object = bookTable.Item(TextBoxISBN.Text)

        If Not foundBook Is Nothing Then

            MessageBox.Show(foundBook.ToString, "Search")
        Else
            MessageBox.Show("Book not found", "Search")

        End If

        clearTextBoxes()
    End Sub

I get the results I expect. The correct books are returns. However, if I put the array into the hashtable and run it with the same search code, my result is "System.Collections.ArrayList." Now I know the search is working because if I search for an ISBN that is not in the hashtable, I get the "Book not found." Where I am getting stuck is displaying the content from that Array instead of the "System.Collections.ArrayList." If I debug, I see that the foundBook in my "If Not foundBook Is Nothing Then" contains exactly the information I expect. I just can't figure out how to get that information to show rather than the "System.Collections.ArrayList." I thought that was what the foundBook.ToString should do.
 
I think I answered my own question by posting my last post. Here is the code that I now have and get what I am looking for.

VB.NET:
    Private Sub ButtonSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSearch.Click
        Dim foundBook As Object = bookTable.Item(TextBoxISBN.Text)

        Dim output As String

        If Not foundBook Is Nothing Then
            For i As Integer = 0 To 3
                output &= foundBook(i) & vbCrLf
            Next
            MessageBox.Show(output, "Search")
        Else
            MessageBox.Show("Book not found", "Search")

        End If

        clearTextBoxes()
    End Sub
 
I still don't see why you're using ArrayLists at all. Like I said earlier, you have specifically defined a Book class to represent a book so why use the inferior ArrayList? If you created Book instances and put them in the Hastable, instead of ArrayLists, then you could just get the Title property, etc., the Book object you retrieve.
 
I still don't see why you're using ArrayLists at all. Like I said earlier, you have specifically defined a Book class to represent a book so why use the inferior ArrayList? If you created Book instances and put them in the Hastable, instead of ArrayLists, then you could just get the Title property, etc., the Book object you retrieve.

Only because the excercise calls for the book to be stored in an arraylist within the hashtable. I would have rather skipped the array.

Thanks for your help. I was even able to get the ButtonAll to work.
 
Last edited:
Back
Top