Logout

GUI Searching of an Array of Objects

And here's a link to the app. example in the video above.

 

**** Note that the full code is below the notes. ****

These notes will take the form of the steps you would take to create a database of objects which can be searched by one criteria in order to find information about a certain object, as in the example above; you type in a country, and get information about that country.


Step 1 - Template Class

Make sure that you have appropriate attributes, a default constructor and other constructors as needed, plus your get methods and set methods.


Step 2 - GUI

A few tabs is a good first step, since there will be the stage where the user creates the database, the one where they search the database, and you will also probably want to display the whole database in a table.

The "Input" and "Search" tabs are straight-forward enough, with input JTextFields, which will use the getText() methods in the Input tab and one getText() and two setText() mehtods in the Search tab.

The table stage is a bit more complex. There are two ways you can have Netbeans help you with table construction; both start with dragging a table onto the frame. You can then right-click on the table and select Table Contents where you can rename rows etc. The other way is to get into the Generated Code and find the code that generates the table, copy and paste it into your own "myInitComponents" method, and change things there. See the code below for how that is done.


Step 3 - Adding to the Array of Objects

The first thing on the agenda will be to make your array of objects as a global variable.

But the very next thing you MUST do is to loop through that array and call one of the constructors for each element of the array. Otherwise, the array remains an array of null pointers, not pointing to any specific instances of your template class.. And that is fine, unless one of the element's attributes is attempted to be accessed by one of the get methods. What will be"got" is a null pointer, and that is an exception and will stop the program execution. Such attempts to access null pointers can often happen inadvertently. A good example of this is if you try to display contents of the whole array without having filled it up.

So the soltion to preventing null pointer exceptions when working with an array of objects, as mentioned above, is to loop through and call one of the constructors for each of the elements. This will use the new operator, which goes and reserves memory for each object, and puts either default values or values you send. If you just call the default construtor (the one with no parameters), which is fine, then the default values that the attributes are assigned in the template class are what are assigned. Or you could opt to send your own default values by calling the constructor which takes in a bunch of parameters.

Then, you will add a new instance of the template class each time the Ok button is clicked on your Input Info tab. In fact, you are overwriting the instance you created with the initializing loop discussed above. So you will need a global counter variable to keep track of which element of the array is next in line to be overwritten. And so the "addition" to the array line will look something like:

countryArray[i] = new Country(countryNameTextField.getText(), Long.parseLong(populationTextField.getText()));

followed by bumping up the counter variable by one:

i++

And you'll also note in the code, at that point it's a good idea to clear the input text fields.


Step 4 - Creating Your Search Methods/Class

It's usually best to keep your sort and search methods off in another class, simply to prevent your GUI file from getting too long and cumbersome to work with; but it's not a requirement.

There's nothing wrong with using a sequential search method if you know your array will not be too large; othewise you'll use a binary search, which requires you to sort as well.

The one thing to look for when copying and pasting search and sort algorithms is that when comparing Strings, you use the compareTo() method, rather than the < and > operators.

You will make sort and search methods specific for the particular attributes that are being used as "key" fields; so for example, if the user types in a country to find a population, the sort and search methods you will need are those for Strings, and the key taken in will be the country.

Within the sorting method, the key thing to remember is that you are comparing by one specific attribute, (so using an arr[i].getSomething()) but swapping the entire objects (so swapping the whole arr[i] object).

And remember that since you are passing objects as parameters, there's no need to return anything, since the called method and the calling call to the method both will be pointing to the same thing, since what is passed is an address.


Step 5 - Displaying The Whole Database

The secret here is to realize that though a table is a two dimensional structure, you don't need a loop within a loop coding structure. You will loop through the rows, but then the inner "looping" through the columns is achieved through individual stagements assigning things to the 0th column, the 1st colulmn, 2nd column, and so on.

The Java method for assigning things to table cells is:

setValueat ( data, row number, column number )

So, for example:

jTable1.setValueAt(countryArray[i].getCountryName(), i, 0);

 

GUI Screen Shots

 

The MainGUI Class:

 package guisearchingobjects;

 public class MainGUI extends javax.swing.JFrame {

     private Country [] countryArray = new Country[300];
 
    private int i = 0; //This is the counter for the addition of elements to the array.

    public MainGUI() {
         initComponents();
         myInitComponents();
     }

     private void myInitComponents() {
         for (int i = 0; i < countryArray.length; i++) {
            countryArray[i] = new Country();
        }
        jTable1.setModel(new javax.swing.table.DefaultTableModel(
             new Object [][] {
                 {null, null, null},
                 {null, null, null},
                 {null, null, null},
                {null, null, null},
                 {null, null, null},
                 {null, null, null},
                 {null, null, null},
                 {null, null, null},
                 {null, null, null},
                {null, null, null},
                {null, null, null},
                 {null, null, null},
                 {null, null, null}
             },
            new String [] {
                "Country Name", "Capital City", "Population"
             }
         ));
     }


                 
 
     private void enterInfoButtonMouseReleased(java.awt.event.MouseEvent evt) {                                              
         // Adding a Country instance each time the button is clicked.
         countryArray[i] = new Country(countryNameTextField.getText(), Long.parseLong(populationTextField.getText()));
         countryNameTextField.setText("");
         populationTextField.setText("");
         i++;
     }                                             
 
     private void jButton1MouseReleased(java.awt.event.MouseEvent evt) {                                       
         // This is just for testing
         jTextField1.setText(countryArray[123].getPopulation()+"");
     }                                      
 


     private void searchButtonMouseReleased(java.awt.event.MouseEvent evt) {                                           
         //Searching for a population of a specific country.
 
         SearchClass sc = new SearchClass();
         int searchResult = -999;
 
         if (!countryInSearchTabTextField.getText().equals("")) {
             sc.selectionSortByCountryName(countryArray);
             searchResult = sc.binarySearchOfCountryName(countryArray, countryInSearchTabTextField.getText());
             populationInSearchTabTextField.setText(countryArray[searchResult].getPopulation() + "");
             capitalInSearchTabTextField.setText(countryArray[searchResult].getCapital());
 
         }else if(!capitalInSearchTabTextField.getText().equals("")) {
             sc.selectionSortByCapital(countryArray);
             searchResult = sc.binarySearchOfCapital(countryArray, capitalInSearchTabTextField.getText());
             populationInSearchTabTextField.setText(countryArray[searchResult].getPopulation() + "");
             countryInSearchTabTextField.setText(countryArray[searchResult].getCountryName());
         }
 
     } 


     private void jTabbedPane1MouseReleased(java.awt.event.MouseEvent evt) {                                           
         // TODO add your handling code here:
         for(int i = 0; i < jTable1.getRowCount(); i++){
             jTable1.setValueAt(countryArray[i].getCountryName(), i, 0);
             jTable1.setValueAt(countryArray[i].getCapital(), i, 1);
             jTable1.setValueAt(countryArray[i].getPopulation(), i, 2);
         }
     } 

 

The Searching And Sorting Class:


 package guisearchingobjects;
 
 public class SearchClass {
 
     public void selectionSortByCountryName(Country[] countryArray) {
         for (int i = 0; i < countryArray.length - 1; i++) {
             int minIndex = i;      
             for (int j = i + 1; j < countryArray.length; j++) {
                 if (countryArray[minIndex].getCountryName().compareTo(countryArray[j].getCountryName()) > 0) {
                     minIndex = j; 
                 }
             }
             if (minIndex != i) {
                 Country temp = countryArray[i];
                 countryArray[i] = countryArray[minIndex];
                 countryArray[minIndex] = temp;
             }
         }
     }
 
     public int binarySearchOfCountryName(Country countryArray[], String countryName) {
         int low = 0;
         int high = countryArray.length - 1;
         while (low <= high) {
             int mid = (low + high) / 2;
             if (countryArray[mid].getCountryName().equals(countryName)) {
                 return mid;
             } else if (countryArray[mid].getCountryName().compareTo(countryName) < 0) {
                 low = mid + 1;
             } else {
                 high = mid - 1;
             }
         }
         return -1;
     }
 }
 
 

 

The Country "Template" Class:

 
 package guisearchingobjects;
 
 public class Country {
     private String countryName = "not set yet";
     private long population = -999;
 
 
     public Country(){
     }

     public Country(String countryName, long population){
         this.countryName = countryName;
         this.population = population;
     }
 
     //Sets:
     public void setCountryName(String countryName){
         this.countryName = countryName;
     }
     public void setPopulation(long population){
         this.population = population;
     }
 
     //Gets:
     public String getCountryName(){
         return countryName;
     }
     public long getPopulation(){
         return population;
     }
 
 }