Section 13.3. Databases: A Place to Store Our Text


[Page 459]

13.3. Databases: A Place to Store Our Text

Large Web sites use databases to store their text and other information. Sites like ebay.com, amazon.com, and CNN.com have large databases with lots of information in them. The pages at these sites aren't generated by somebody typing in information. Instead, programs walk over the database gathering all the information and generating HTML pages. They might do this on a timed basis, to keep updating the page. (See the "last generated" information at CNN.com or Google News.)

Why do they use databases rather than simple text files? There are four reasons:

  • Databases are fast. Databases store indices that keep track of where key information (like last name or ID number) is in a file, so that you can find "Guz-dial" right away. Files are indexed on filename, but not on the content in the file.

  • Databases are standardized. You can access Microsoft Access, Informix, Oracle, Sybase, MySQL databases from any number of tools or languages.

  • Database access can be distributed. Multiple people can be putting information into a database and pulling information out of a database, from different computers across a network.

  • Databases store relations. Databases store names for the fields of data. When databases know which fields are important (e.g., which ones you're going to search on most often), the database can be indexed on those fields.

A database stores data based on keys. Keys are unique identifiers for a row in a table of information.

13.3.1. Key and Value Maps

In Java you can use a java.util.Map to store key and value pairs. Both the keys and the values must be objects. Maps can't have duplicate keys. Each key will map to only one value. However, you can have duplicate values.

Have you ever seen a bunch of post office boxes at your post office? Each of these is like a map in that you can take something out of the box if you have the key. You can also put something into the box if you have the key.

Map is actually an interface. Several classes implement this interface (HashMap, TreeMap, Hashtable, ...). We will use the class java.util.HashMap to create a map from a husband's name to his wife's name.

> import java.util.*; > Map wifeMap = new HashMap(); > wifeMap.put("Fred","Wilma"); > wifeMap.put("Barney","Betty"); > System.out.println("Fred's wife is " + wifeMap.get("Fred")); Fred's wife is Wilma > System.out.println("Barney's wife is " + wifeMap.get("Barney")); Barney's wife is Betty



[Page 460]

Notice that we can refer to a HashMap object with an object reference of type Map. Since the class HashMap implements the Map interface we can use just the interface name as the type. This allows us to easily change this to another class that implements the Map interface in the future without changing many lines of code. If in the future we want to keep the keys in sorted order, we could use a treeMap instead.

You can put any object in a map as the key and any object in a map as a value. You can even create a map that has another map as the value. Here we have created a map of categories with two categories to start with: "friends" and "family". Each of these keys maps to another map with a name as the key and a phone number as a value.

> import java.util.*; > Map categoryMap = new HashMap(); > Map friendsMap = new HashMap(); > Map familyMap = new HashMap(); > categoryMap.put("friends",friendsMap); > categoryMap.put("family",familyMap); > friendsMap.put("Suz","555 213-2392"); > friendsMap.put("Shayna","555 421-3938"); > familyMap.put("Mom","555 321-3928"); > familyMap.put("Dad","555 321-3927");


What if you want to store phone numbers on your computer? And what if you want a way to quickly look up the phone number for a given name. A map makes it very easy to look up a value given a key. We can use a map of a name to a phone number. Let's create a class PhoneBook which will have a field that is a map of names to phone numbers. We will want to keep the names and phone numbers around, so we will read them from a file. That way we can edit the file to add or remove names and phone numbers.

13.3.2. Downcasting

Maps hold key and value pairs where both the key and value are objects. But, what if we actually use a String object for the key and value? This is allowed because the String class inherits from the Object class so it is a type of object. But what if we want to use it as a String object again when we get it back from a map?

> import java.util.*; > Map testMap = new HashMap(); > testMap.put("theKey","theValue"); > String value = testMap.get("theKey"); Error: Bad types in assignment


Why do we get an error? The value is an object of the String class. Yes, but the compiler doesn't know that. All the compiler knows is that the map holds objects, not strings. We need to tell it to convert the type to String using a cast. You may remember casting as the way that we told the compiler that we were aware that putting a double value into an integer value could lose data.


[Page 461]
> int floor = 1.0 / 3; Error: Bad types in assignment > int floor = (int) 1.0 / 3; > System.out.println(floor); 0


We need to do the same thing when we convert a type from a more general type to a more specific type. This is also called downcasting. It tells the compiler to use the specified type for the object. Of course, you could get a runtime exception, if the object isn't really of the type that you are trying to cast it into.

> Integer intObj = (Integer) testMap.get("theKey"); java.lang.ClassCastException: intObj


Here is the class that represents a phone book. Notice that the method getPhone-Number does use a downcast to change the object (the phone number) returned from the Map to type String.

Program 122. Phone Book Class
(This item is displayed on pages 461 - 463 in the print version)

import java.util.*; import java.io.*; /**  * A class that represents a phone book.  This phone  * book maps names to phone numbers. This will  * read the phone book information from a file.  */ public class PhoneBook {   /////////////////// fields /////////////////////////   private String fileName;   private Map phoneMap = new HashMap();   ////////////////// constructors ////////////////////   /**    * Constructor that takes a file name and reads    * in the names and phone numbers from a file    * @param file the name of the file to read    */   public PhoneBook(String file)   {     this.fileName = file;     // read the map information in from the file     readInfoFromFile();   } 
[Page 462]
/////////////////// methods ///////////////////// /** * Get the phone number for the passed name * @param name the name to look up in the map * @return the phone number if found, else null */ public String getPhoneNumber(String name) { String phoneNumber = (String) phoneMap.get(name); return phoneNumber; } /** * Method to read the phone information from a * file and use it to fill the map */ public void readInfoFromFile() { String line = null; String[] phoneArray = null; try { // create the reader BufferedReader reader = new BufferedReader(new FileReader(fileName)); // loop reading from the file while ((line = reader.readLine()) != null) { if (line.indexOf(":") >= 0) { phoneArray = line.split(":"); phoneMap.put(phoneArray[0].trim(), phoneArray[1].trim()); } } // close the reader reader.close(); } catch (FileNotFoundException ex) { SimpleOutput.showError("Couldn't find file " + fileName); } catch (Exception ex) { ex.printStackTrace(); } }
[Page 463]
/* main for testing */ public static void main(String[] args) { PhoneBook phoneBook = new PhoneBook("barbsPhoneBook.txt"); System.out.println(phoneBook.getPhoneNumber("Shayna")); System.out.println(phoneBook.getPhoneNumber("Dentist")); } }


13.3.3. Generics

Java version 5.0 (also known as 1.5) added generics. You can use generics to specify the type of objects used in collections and this eliminates the need to downcast when you get objects back from a collection. To use generics you simply add type information when you declare a variable that refers to a collection object and when you create a collection object. To declare a field that is a map with String objects used as both the keys and the values use:

private Map<String,String> phoneMap =     new HashMap<String,String>();


Doing this eliminates the need to cast the value returned from the collection to a string when you assign it to a variable that refers to an object of the String class.

String phoneNumber = phoneMap.get(name);


Here is the PhoneBook class changed to use generics.

Program 123. Java 5.0 Version of the Phone Book
(This item is displayed on pages 463 - 465 in the print version)

import java.util.*; import java.io.*; /**  * A class that represents a phone book.  This phone  * book maps names to phone numbers. This will  * read the phone book information from a file.  */ public class PhoneBook {   /////////////////// fields /////////////////////////   private String fileName;   private Map<String,String> phoneMap =     new HashMap<String,String>();   ////////////////// constructors ////////////////////   /**    * Constructor that takes a file name and reads    * in the names and phone numbers from a file 
[Page 464]
* @param file the name of the file to read */ public PhoneBook(String file) { this.fileName = file; // read the map information in from the file readInfoFromFile(); } /////////////////// methods ///////////////////// /** * Get the phone number for the passed name * @param name the name to look up in the map * @return the phone number if found, else null */ public String getPhoneNumber(String name) { String phoneNumber = phoneMap.get(name); return phoneNumber; } /** * Method to read the phone information from a * file and use it to fill the map */ public void readInfoFromFile() { String line = null; String[] phoneArray = null; try { // create the reader BufferedReader reader = new BufferedReader(new FileReader(fileName)); // loop reading from the file while ((line = reader.readLine()) != null) { if (line.indexOf(":") >= 0) { phoneArray = line.split(":"); phoneMap.put(phoneArray[0].trim(), phoneArray[1].trim()); } } // close the reader reader.close();
[Page 465]
} catch (FileNotFoundException ex) { SimpleOutput.showError("Couldn't find file " + fileName); } catch (Exception ex) { ex.printStackTrace(); } } /* main for testing */ public static void main(String[] args) { PhoneBook phoneBook = new PhoneBook("barbsPhoneBook.txt"); System.out.println(phoneBook.getPhoneNumber("Shayna")); System.out.println(phoneBook.getPhoneNumber("Dentist")); } }


What if we want to print out all of the names and phone numbers in the phone book? How can we loop through a Map? You can get a set of all of the keys in a map using the method keySet(). This returns an object of a class that implements the java.util.Set interface. A set is something that holds non-duplicate items. It may not preserve the order of the items in the set. Contrast this with the List interface, which does preserve the order of the items in the list, and does allow duplicate items in the list.

If you are using Java 5.0 (1.5) or above, you can loop through the items in a set using a for-each loop. Here is a method that will print out all the data in the phone book.

Program 124. The Method printBook with a for-each Loop

public void printBook() {    // get the set of keys    Set<String> keySet = phoneMap.keySet();    // loop through the keys    for (String key : keySet)    {      System.out.println("Name: " + key +                         ", Phone number: " +                         phoneMap.get(key));    } }


Another way to loop through a collection is to use another interface: java.util. Iterator. Classes that implement this interface will let you walk through the elements of a collection one at a time using the method next() and you can check if there are more items to process using the method hasNext(). You will need to downcast the object returned from the Iterator if you want to treat it as anything other than an object.


[Page 466]

Here is the 1.4 version of the method printBook:

Program 125. The Method printBook with an Iterator

/**  * Method to print out the contents of the phone book  */ public void printBook() {   // get the set of keys   Set keySet = phoneMap.keySet();   String key = null;   // loop through the keys   Iterator iterator = keySet.iterator();   while (iterator.hasNext())   {     key = (String) iterator.next();     System.out.println("Name: " + key +                        ", Phone number: " +                        phoneMap.get(key));   } }




Introduction to Computing & Programming Algebra in Java(c) A Multimedia Approach
Introduction to Computing & Programming Algebra in Java(c) A Multimedia Approach
ISBN: N/A
EAN: N/A
Year: 2007
Pages: 191

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net