Storing Objects in Java
by Thomas Paul
|
Type |
Test size |
Put |
Get |
Iteration |
---|---|---|---|---|
TreeMap |
10 |
26.5 |
15.6 |
56.3 |
100 |
31.7 |
18.9 |
35.16 |
|
1000 |
26.9 |
21.7 |
7.0 |
|
HashMap |
10 |
14.0 |
11.0 |
28.1 |
100 |
12.2 |
12.6 |
38.9 |
|
1000 |
9.2 |
12.3 |
7.0 |
|
Hashtable |
10 |
15.6 |
12.5 |
51.6 |
100 |
20.2 |
14.7 |
49.8 |
|
1000 |
12.1 |
18.8 |
9.6 |
|
IdentityHashMap |
10 |
18.8 |
25.0 |
35.9 |
100 |
22.2 |
25.3 |
32.6 |
|
1000 |
18.8 |
25.2 |
6.3 |
|
LinkedHashMap |
10 |
20.3 |
10.9 |
23.5 |
100 |
18.9 |
11.6 |
17.7 |
|
1000 |
14.5 |
12.0 |
3.3 |
Figure 1: relationships between the classes and interfaces of the Map interface
The map interface contains one static nested interface, Map.Entry which we will discuss in a moment. The Map
contains the basic methods for all Map implementations such as put and get. In addition, the Map provides three
separate ways to get objects from it as Collection objects. You can get a Set of keys, a Collection of values,
or a Set of key-value pairs stored in a Map.Entry object.
Here are some of the key methods of the Map interface:
The Map interface contains a static nested interface called Entry. This interface is used to access key-value pairs as individual objects outside of the Map. The entrySet( ) method can be used to get individual key-value pairs out of the Map. You can then use methods of the Map.Entry interface to get the key or valu out of the Object.
Here are some of the key methods of the Map.Entry interface:
The HashMap class is the simplest implementation of the Map interface. The HashMap does not add any additional
methods (other than clone) beyond those found in the Map interface. The HashMap achieves good performance
by using a hash to store the key in the Map. The hash allows fast lookup which means that the containKey( ) method
will perform much better than the containsValue( ) method. Any Object used as a key in a HashMap must implement
the hashCode( ) and equals( ) methods. See Part 2 of this series for a discussion of this issue.
The HashMap does not guarantee the order of the items in the Map and allows one null key. Duplicates are not permitted.
The HashSet offers "constant time" performance for lookups involving the key and linear time for lookups
based on value. This means that adding items to the Map will not cause significant performance degradation as long
as lookups are done by the key. The performance of basic functions such as put, remove, get, etc is based on two
factors which can be specified in the constructor of the HashMap, initial capacity and load factor. See the HashSet
discussion in Part 2 of this series for the further discussion of these parameters.
New to J2SE 1.4, the LinkedHashMap class is used in exactly the same way as the HashMap class. It has no additional methods but it does have one additional constructor that we will discuss in a moment. The basic difference between HashMap and LinkedHashMap is that the LinkedHashMap maintains the order of the items added to the Map. It does this by maintaining a doubly linked list containing the hash and the original order of the items. According to Sun, the LinkedHashMap should run nearly as fast as the HashMap.
The LinkedHashMap has one additional constructor that takes an additional boolean parameter. This allows you to construct a LinkedHashMap that maintains items, not in the order that they are added to the Map but rather in the order in which they are accessed.
Part of Java since JDK 1.0, the Hashtable class is a synchronized implementation of the Map interface. It has three methods that are not part of the Map interface (contains, keys, and elements) that should be avoided since the Map interface has methods (containsValue, containsKey, and values) that provide the identical functionality. The main difference between HashMap and hashtable is that the hashtable is synchronized, hoewever, synchronization can be achieved by using the Collections.synchronizedMap method on the HashMap. The Hashtable does not permit null keys or null values. The Hashtable should be treated as a class left in java to support maintenance of older programs.
The WeakHashMap is virtually identical to the HashMap. The difference is that entries in this class do not count as a reference against the key contained in this Map. This means that over time, the garbage collector may remove keys from the WeakHashMap and garbage collect the object. This would give the appearance that objects are being removed from the Map. The size( ) method may return different values over time. The isEmpty( ) method may return false and then true. Value objects in the WeakHashMap will be garbage collected only if their key is removed and they have no other reference to them. It should be noted that if the value object has a reference to its own key object, the key objetc will not be garbage collected. This situation should be avoided.
The IdentityHashMap is also like the HashMap with the exception that a key is considered equal to another key only if they are pointing to the exact same object. Other implementations of Map use the equals( ) method to determine if two keys are equal. The IdentityHashMap uses the == comparator. Two keys (a and b) are considered equal if a == b. The IdentityhashMap should only be used in the cases where this functionality is required. It should not be used otherwise.
The TreeMap class guarantees that the keys in the Map will be sorted in ascending order by either the keys natural order or by a Comparator provided to the constructor of the TreeMap. Searching for an item in a TreeMap will be slower than in a HashMap because the hashing algorithm gives better performance than the compareTo() method which is used to locate items in a TreeMap. In part 2 of this series, we discussed how to control the sorting of the TreeSet. The same methods apply to controlling the sorting of the TreeMap.
TreeMap does add several new methods to the Map interface.
The Properties class is very simialr to the Hashtable and has been part of Java since JDK 1.0. The Properties class adds additional functionality that can be extremely useful. The Properties class represents a persistent list of properties. What exactly does this mean? The Properties class is designed to provide methods to store and load files containing key-value pairs as Strings. Properties files are simply key-value pairs where the key and value are separated by an "=" (name=Tom) and eack key-value pair is on a separate line. A Windows ini file is an example of a properties file. In many cases, XML files are replacing properties files but the simplicity of a properties file combined with its ease of use makes the Properties class still a very useful class.
Although the Properties file inherits the methods of the Hashtable, it is recommended that the Hashtable put method not be used as this may allow the insertion of non-String objects. Only Strings should be used as either a key or a value in a Properties object. A Properties object with a non-String in it will throw an exception if you attempt to store it to a file. A Properties object can contain another Properties object (specified in the constructor) which is used as the default keys if no matching key is found in the Properties object.
The Properties class provides several new methods:
Here is an example of reading in a properties file, removing the password and printing out the reaminder. As you can see, using the Properties class is very simple.
import java.util.*; import java.io.*; public class PropsDemo { public static void main(String[] args) throws Exception { BufferedInputStream bStream = new BufferedInputStream(new FileInputStream("prefs.ini")); Properties props = new Properties(); props.load(bStream); props.remove("password"); props.list(System.out); bStream.close(); } }
We have taken a quick look at the main implementations of the Map interface and also examined how we can make
use of properties files. As we have seen, there are quite a few Map objects and which Map object you wish to use
will depend greatly upon how you intend on using it in your application. Like the Set interface, performance is
less a concern in choosing among Map objects. The main concern is the functionality you require.
Next month we will wrap up this series and take a look at the many additional functions found in the Collections
class.
Cindy's Segment - a Whimsical View of the World
Now just close your eyes and imagine that you ARE your favorite class. Then answer each of the questions below, and find out just how classy you really are.
Object Oriented Personality Quiz Pick the answer that best describes your personality: I. In your class, when comparing yourself to others: (select one)
1. You do not override the equals() method of Object. 2. You do not believe that your equals() method would ever be invoked even if you had one. 3. You do not override the equals() method, but one of your super classes HAS. 4. You have an equals() method of your own. Analysis:- If you selected:
1. You believe yourself to be unique and unequaled. The only thing that you will say that you are equal to is yourself. If you happen to be a dynamic personality, such as a Thread, rather than a stable personality with a value, this MAY be true. On the other hand, you may just not CARE whether anybody has a clue who you are equal to and you are perfectly happy letting everyone think that you are only equal to yourself. Quite an egotistic attitude. 2. You are a very private sort, and do not go out much. You believe yourself to be invisible to anyone that would ever possibly use the equals() method. You need to get a grip on yourself and work on self-confidence. Get out there and GET an equals() method - it is the right thing to do. 3. You are content to be judged based on the rules laid out by your ancestors. You are confident that whatever they said is good enough for you. Basically, you are afraid to strike out on your own and define your own personality. You are a wimp. 4. You are a personality in your own right. You are attempting to be a mature, well rounded class and live up to your responsibilities. Now check out the next question to find out how well you are doing with your equals() method. II. When invoking your equals() method on an instance of your class: (answer each one true or false)
1. When comparing the instance to itself, your equals() method always returns ?true?. 2. When comparing the instance to a second instance of your class, you always get the same result as if the second instance compares itself to the original. 3. When comparing the instance to a second instance many times, you always get the same answer (presuming that the instances are not modified). 4. When you compare the instance to ?null? your equals() method always returns ?false?. 5. When you say that instance 1 is equal to instance 2 and instance 2 is equal to instance 3, then it is always true that instance 1 is equal to instance 3. 6. You answered false to any of the above. Analysis:- If you answered true:
1. Your reflexive instincts are good, which means that you have a solid sense of self identity. 2. You are fair and symmetric. You are not influenced by who is asking the question. 3. You are consistent and stable. You can be relied on and trusted. You are really cool. 4. You can recognize thin air on your own. This is a basic survival requirement. 5. You are capable of the higher level of consciousness known as transitiveness. 6. You have a problem. Get help immediately. III. When you overrode the equals() method: (answer each one true or false)
1. You made sure to leave the argument of the equals(Object o) method as Object. 2. You always use the instanceof operator to check if the incoming argument is the correct type. 3. You start out with a check to see if you are comparing the instance to itself by using a == check. 4. Your method checks each field of the class one by one, comparing the contents of both objects to insure that each field is equal. 5. You have identified any unreliable sources that might change without you knowing it and omitted them from the comparison. 6. You overrode the hashCode() method also. 7. You answered false to any of the above. Analysis:- If you answered true:
1. Of course the only thing coming in should always be ?MyType? but you have resisted the urge to state that in the signature, and therefore you have avoided accidentally overloading equals(Object o) instead of overriding it. You have shown exceptional willpower. Good Job! 2. Well, you left the door open for this above, so you just have to deal with it. And yes - this is a bit of an elitist attitude, but the facts of life say that you just can NEVER be the same as any other type than you ARE, so trying to compare yourself to others is a bad idea. 3. You are not easily hoodwinked. You check for obvious set-ups before putting any effort into comparisons. 4. You are methodical and complete. You do not let complexity overwhelm you. 5. You recognize flighty characteristics in yourself and do not use those aspects of your personality in defining yourself. Of course this means that your instance might be considered equal to some instance that has a different value in that field, but you have acknowledged that, come to terms with it and moved on. 6. You recognize that when defining your equals() method, you are defining what makes you unique, and that eventually someone is going to want to put some order to your instances, and they will without a doubt use the hashCode() method to do that. In fact since all the HashMap, HashSet, etc. classes count on this method working hand in hand with equals, you KNOW that this is important. 7. Once again, you have a problem. Get help immediately. Professional help. IV. When you overrode the hashCode() method: (answer each one true or false)
1. You didn?t, even though you overrode the equals() method. 2. Your hashCode() method always returns the same value for every instance. 3. Your hashCode() method returns the same value for several instances that are NOT equal. 4. Your hashCode() method always returns the same value for the same instance over and over unless you start your application over, then it consistently returns a different value. 5. Your hashCode() method returns different values for different instances even if they are considered equal using your equals() method. 6. Your hashCode() method skips some fields in your object state because that way the hashCode() method runs faster. 7. Your hashCode() method returns something other than an int value. Analysis:- If you answered true:
1. You fool! The hashCode() method MUST return the same result for all instances that are equal. When you changed the definition of what makes instances equal, you have to let hashCode() in on the secret or nothing will work as expected. You can plan on spending much of your life in confusion. 2. You try to get away with whatever you can. You feel that because this will compile and run, that you have done your duty. Even if it runs REALLY POORLY, which this will. 3. You play by the rules. Exactly. And that is fine. However, you are NOT expecting optimal performance, which is good, because you will probably not get it if there are too many instances that get identical results. 4. You are not chained by the opinions of others. You know that this is valid EVEN IF it bothers others, and you stand your ground. 5. You have no internal integrity. You are confused and mixed up and will spread that condition to all who interact with you. 6. You are easily confused and do not recognize the difference between immediate savings and long term benefits. You will spend much of your life waiting for hash-based activities to complete because they could be extremely slow. Learn to appreciate boredom. 7. Careful, the compiler will get you. V. When you overrode the equals() method: (Select one)
1. You also overrode the toString() method, however the output String sort of reads like a core dump. You did not implement the Comparable interface. 2. You also overrode the toString() method trying to make the output String as readable as possible. You did not implement the Comparable interface. 3. You also overrode the toString() method trying to make the output String as readable as possible. You also implemented the Comparable interface. 4. You also overrode the toString() method trying to make the output String as readable as possible and as inclusive of all of the fields as possible. You also implemented the Comparable interface and did it well. Analysis:- If you selected:
1. You are a techno-weenie at heart and should not be allowed to participate in design decisions. All of your code should be reviewed by persons resembling humans before being released for public consumption. 2. You are competent, but do not go the extra mile. Adequate is good enough for you. 3. You try to excel at everything, and often succeed. If you did a good job at implementing the Comparable contract then you should be proud of yourself. 4. So you are James Gosling!! Well, maybe Joshua Bloch. I knew that JavaRanch would rope you guys in sooner or later. Can we see the code???? |
Copyright ? 2002. Cindy Glass. All rights reserved.
Graphics by Pauline McNamara and Stephanie Grasson
Next month - "Asserting Yourself in Public"- or - "Testing your Skills"
?
?
The Cattle Drive forum is where the drivers get together to complain, uh rather, discuss their assignments and encourage each other. Thanks to the enthusiastic initiative of Johannes de Jong, you can keep track of your progress on the drive with the Assignment Log. If you're tough enough to get through the nitpicking, you'll start collecting mooses at the Cattle Drive Hall of Fame.
Gettin' them doggies...
This month the number of Cattle Drivers wrastlin' Java code has
stayed around 20. The Servlets corral has the most ropin' going on,
followed closely by the activity in the Java Basics corral. More
than half of the drivers on the assignment log are busy with OOP,
Servlets and JDBC.
Fresh riders on the Drive...
A big welcome to the new riders on the log: Bryant
Constant, Jeremy Thorton, JD Lambert and Brian
Coates. Check yer spurs folks, you'll be needin' em!
Another moose on the wall
for...
Yep, that's right, you make it through, you get yerself a nice
little moose to hang on the wall. Well, OK, so it's a virtual moose
on a virtual wall, but you can be right proud of 'em! Thanks to the
efforts of Marilyn deQueiroz, you can now proudly admire your
codin' accomplishments at the recently opened Cattle Drive Hall of Fame. Check it out, pardner, it's
worth a wink.
This month Gerald Dettler showed lots of persistence and bagged a moose on the OOP trail of the drive. Way to go Gerald! Congrats also to Louise Haydu, who picked up a Servlets moose, no easy task!
Saddle sore...
So close and yet so far, that's how it feels when you're just
about to get through one of the Cattle Drive sections. Two
consistent riders, Manju Jain and Louise Haydu, are
both just about done with those Servlets assignments. Hang in
there, cowpokes, yer almost there!
Changin' hands at the reins...
You'll notice another new moderator at the Cattle Drive forum:
Dirk Schreckmann, the fastest Cattle Driver in the west, is
stepping in to help out with all those wild riders, while Pauline
McNamara eases up on her Cattle Drive chores. Big thanks
Dirk!
Nitpicking is hard work too...
We know they're workin' reeeeeally hard, after all, we've seen what
those assignments look like once the nitpickers have combed through
'em. Hats off to Marilyn deQueiroz and Jason Adam for their dedication and patience with the
pesky vermin that always manage to make their way into those
assignments. Newbie nitpicker Pauline McNamara has started collecting nits too.
Tips for the Trail...
Ever get one of those nitpicks about optimization? Yer not alone
pardner. So here's a couple sources of inspiration for yer tough
optimization decisions: check out this thread over at the CD forum. Happy
codin'!
Written by Pauline McNamara
SCWCD Exam Study Kit by Hanumant Deshmukh and Jigneh Malavia |
||
The book is laid out in a logical straightforward fashion -- matching up exam objectives with Servlet/JSP topics and even covers a couple things that aren't (yet) on the exam, like Filters. It's written in a very easy-to-read, conversational tone and is an excellent resource for someone who's familiar with Java but not with Servlets and JSPs or even for someone familiar with them, but needs to brush up on some of the details for the exam.
The bundled CD that comes with the book is chock full of excellent resources (3 JwebPlus mock exams, Tomcat 4, the relevant JSP and Servlet specs, and an electronic copy of the book). The quizlets and notes intermixed within each chapter help you to confirm that you understood what you just read -- and also explain a couple ?gotchas?. The author's website contains a excellent little forum where you can get hold of the author's to ask questions or report errors in the book. I'll definitely use this book as a resource even after the exam. (Jessica Sant - Bartender, July 2002) More info at Amazon.com || More info at Amazon.co.uk |
Starting Date | Book | Author(s) | Publisher | JavaRanch Forum |
Aug 6 | Java Development with Ant | Erik Hatcher Steve Loughran |
Manning Publications Co. | Jakarta Projects |
Aug 13 | Learn Java with JBuilder 6 | John Zukowski | APress | IDE's and other tools |
Aug 20 | JSTL in Action | Shawn Bayern | Manning Publications Co. | JSP |
Aug 27 | JSP Examples and Best Practices | Andrew Patzer | APress | JSP |
For more information on JavaRanch's Giveaways see Book Promotion Page.
As always JavaRanch is dedicated to providing you with the best source of information on Java Programming and Engineering.
by Carl Trusiak
Managing Editor: Carl Trusiak
Comments or suggestions for JavaRanch's NewsLetter can be sent to the NewsLetter Staff
For advertising opportunities contact NewsLetter Advertising Staff