Chapter 11: Collections and Maps

Similar documents
The class Object. Lecture CS1122 Summer 2008

The Object Class. java.lang.object. Important Methods In Object. Mark Allen Weiss Copyright 2000

Super-Classes and sub-classes

For this section, we will implement a class with only non-static features, that represents a rectangle

Programming Languages and Techniques (CIS120)

Polymorphism. return a.doublevalue() + b.doublevalue();

Collections. Powered by Pentalog. by Vlad Costel Ungureanu for Learn Stuff

Methods Common to all Classes

Creating an Immutable Class. Based on slides by Prof. Burton Ma

Java Fundamentals (II)

Canonical Form. No argument constructor Object Equality String representation Cloning Serialization Hashing. Software Engineering

Inheritance (Part 5) Odds and ends

equals() in the class Object

CLASS DESIGN. Objectives MODULE 4

Operators and Expressions

Graphical Interface and Application (I3305) Semester: 1 Academic Year: 2017/2018 Dr Antoun Yaacoub

java.lang.object: Equality

Language Features. 1. The primitive types int, double, and boolean are part of the AP

Review. CSE 143 Java. A Magical Strategy. Hash Function Example. Want to implement Sets of objects Want fast contains( ), add( )

Advanced Topics on Classes and Objects

For more details on SUN Certifications, visit

JAVA WRAPPER CLASSES

Advanced Programming - JAVA Lecture 4 OOP Concepts in JAVA PART II

MIT AITI Lecture 18 Collections - Part 1

Domain-Driven Design Activity

Abstract Classes and Interfaces

1 Shyam sir JAVA Notes

CSC 1351: Final. The code compiles, but when it runs it throws a ArrayIndexOutOfBoundsException

CSE 331 Software Design & Implementation

Expected properties of equality

Sorting and searching arrays

CSE 331 Software Design & Implementation

Today. Reading. Homework. Lecture Notes CPSC 224 (Spring 2012) hashcode() method. Collections class. Ch 9: hw 7 out (due in a week)

Class, Variable, Constructor, Object, Method Questions

COE318 Lecture Notes Week 8 (Oct 24, 2011)

Fall 2017 Mentoring 9: October 23, Min-Heapify This. Level order, bubbling up. Level order, bubbling down. Reverse level order, bubbling up

CMSC131. Inheritance. Object. When we talked about Object, I mentioned that all Java classes are "built" on top of that.

Programming Languages and Techniques (CIS120)

MET08-J. Preserve the equality contract when overriding the equals() method

The Sun s Java Certification and its Possible Role in the Joint Teaching Material

JAVA MOCK TEST JAVA MOCK TEST III

Distributed Systems Recitation 1. Tamim Jabban

INSTRUCTIONS TO CANDIDATES

Equality for Abstract Data Types

Programming Languages and Techniques (CIS120e)

Agenda. Objects and classes Encapsulation and information hiding Documentation Packages

COE318 Lecture Notes Week 9 (Oct 31, 2011)

Name Return type Argument list. Then the new method is said to override the old one. So, what is the objective of subclass?

Overloaded Methods. Sending Messages. Overloaded Constructors. Sending Parameters

TeenCoder : Java Programming (ISBN )

Programming Languages and Techniques (CIS120)

COP 3330 Final Exam Review

CS/B.TECH/CSE(New)/SEM-5/CS-504D/ OBJECT ORIENTED PROGRAMMING. Time Allotted : 3 Hours Full Marks : 70 GROUP A. (Multiple Choice Type Question)

Uguaglianza e Identità. (no, non avete sbagliato corso )

C12a: The Object Superclass and Selected Methods

Distributed Systems Recitation 1. Tamim Jabban

Fundamental Java Methods

CompuScholar, Inc. 9th - 12th grades

The Java Type System (continued)

CMSC 341. Nilanjan Banerjee

Elementary Symbol Tables

Introduction to Programming Using Java (98-388)

Principles of Software Construction: Objects, Design and Concurrency. Inheritance, type-checking, and method dispatch. toad

CS260 Intro to Java & Android 03.Java Language Basics

Programming Languages and Techniques (CIS120)

1.00/1.001 Introduction to Computers and Engineering Problem Solving. Final Exam

Lecture 4: Extending Classes. Concept

Equality. Michael Ernst. CSE 331 University of Washington

Rules and syntax for inheritance. The boring stuff

Outline. Java Models for variables Types and type checking, type safety Interpretation vs. compilation. Reasoning about code. CSCI 2600 Spring

Inheritance. Inheritance allows the following two changes in derived class: 1. add new members; 2. override existing (in base class) methods.

Day 4. COMP1006/1406 Summer M. Jason Hinek Carleton University

CS/ENGRD 2110 FALL Lecture 7: Interfaces and Abstract Classes

Java Classes. Produced by. Introduction to the Java Programming Language. Eamonn de Leastar

Equality. Michael Ernst. CSE 331 University of Washington


Introducing Hashing. Chapter 21. Copyright 2012 by Pearson Education, Inc. All rights reserved

1. Every program must have at least one class declaration. (*) 2. Every class declared in a program must have a distinct identifier.

Chair of Software Engineering. Languages in Depth Series: Java Programming. Prof. Dr. Bertrand Meyer. Exercise Session 10

Object-Oriented Programming in the Java language

Inheritance. The Java Platform Class Hierarchy

CS-140 Fall 2017 Test 2 Version A Nov. 29, 2017

The Liskov Substitution Principle

Announcements. Equality. Lecture 10 Equality and Hashcode. Announcements. CSE 331 Software Design and Implementation. Leah Perlmutter / Summer 2018

CHETTINAD COLLEGE OF ENGINEERING & TECHNOLOGY JAVA

Introduction to Object-Oriented Programming

Selected Java Topics

Arrays. Chapter Arrays What is an Array?

Software and Programming I. Classes and Arrays. Roman Kontchakov / Carsten Fuhs. Birkbeck, University of London

Hash tables. hashing -- idea collision resolution. hash function Java hashcode() for HashMap and HashSet big-o time bounds applications

Java Magistère BFA

Oracle 1Z Java Standard Edition 5 Programmer Certified Professional.

Chapter 1: Introduction to Computers, Programs, and Java

Equality in.net. Gregory Adam 07/12/2008. This article describes how equality works in.net

Programming Languages and Techniques (CIS120)

Conversions and Casting

Inheritance. Notes Chapter 6 and AJ Chapters 7 and 8

Points To Remember for SCJP

Principles of Software Construction: Objects, Design and Concurrency. Polymorphism, part 2. toad Fall 2012

CS-202 Introduction to Object Oriented Programming

Transcription:

Chapter 11: Collections and Maps Implementing the equals(), hashcode() and compareto() methods A Programmer's Guide to Java Certification (Second Edition) Khalid A. Mughal and Rolf W. Rasmussen Addison-Wesley, 2nd. Edition, 2003. ISBN 0-201-72828-1 E-mail: pgjc2e@ii.uib.no Web site: http://www.ii.uib.no/~khalid/pgjc2e/ Permission is given to use these notes in connection with the book. Modified: 8/3/06 PGJC2E 11: Collections and Maps 11-1/33

11.7 Implementing the equals(), hashcode() and compareto() methods The majority of the non-final methods of the Object class provide general contracts for objects, which the classes overriding the methods should honor. Objects of a class that override the equals() method can be used as elements in a collection. If they override the hashcode() method, they can also be used as elements in a HashSet and as keys in a HashMap. Implementing the Comparable interface allows them to be used as elements in sorted collections and sorted maps. PGJC2E 11: Collections and Maps 11-2/33

Example: Version Number (VNO) A version number (VNO) for a software product comprises three pieces of information: a release number a revision number a patch number Ranking version numbers chronologically: The release number is most significant. The revision number is less significant than the release number, and the patch number is the least significant. PGJC2E 11: Collections and Maps 11-3/33

The equals() method If every object is to be considered unique, then it is not necessary to override the equals() method in the Object class -- the most discriminating equivalence relation. Example 11.7 A Simple Class for Version Number public class SimpleVNO { // Does not override equals() or hashcode(). private int release; private int revision; private int patch; public SimpleVNO(int release, int revision, int patch) { this.release = release; this.revision = revision; this.patch = patch; public String tostring() { return "(" + release + "." + revision + "." + patch + ")"; PGJC2E 11: Collections and Maps 11-4/33

Using the SimpleVNO class See class TestVersionSimple in Example 11.8 which uses objects of the class SimpleVNO. Method makeversion() creates a version number. The versions array and the downloads array represent a list of version numbers and their corresponding downloads, respectively. Test object reference equality and object value equality. The result is always false, (6) - (9). The equals() method is not overridden. Test searching in an array. Search in the versions array will always fail, (10) - (13), as the equals() method is not overridden. Test for membership in a collection. The result is always false, (14) - (15), as the equals() method is not overridden. Test for membership in a map. The result is always false, (16) - (21), as the hashcode() method is not overridden. Test for usage in a sorted collection and map. Exception thrown, (22) - (23), as the compareto() method of the Comparable interface is not implemented. PGJC2E 11: Collections and Maps 11-5/33

Example 11.8 Implications of not overriding the equals() method import java.util.*; public class TestVersionSimple { public static void main(string[] args) { (new TestVersionSimple()).test(); protected Object makeversion(int a, int b, int c) { return new SimpleVNO(a, b, c); protected void test() { // Three individual version numbers. Object latest = makeversion(9,1,1); // (1) Object inshops = makeversion(9,1,1); // (2) Object older = makeversion(6,6,6); // (3) // An array of version numbers. Object[] versions = { // (4) makeversion( 3,49, 1), makeversion( 8,19,81), makeversion( 2,48,28), makeversion(10,23,78), makeversion( 9, 1, 1); // An array of downloads. PGJC2E 11: Collections and Maps 11-6/33

Integer[] downloads = { // (5) new Integer(245), new Integer(786), new Integer(54), new Integer(1010), new Integer(123); // Various tests. System.out.println("Test object reference and value equality:"); System.out.println(" latest: " + latest + ", inshops: " + inshops + ", older: " + older); System.out.println(" latest == inshops: " + (latest == inshops)); // (6) System.out.println(" latest.equals(inshops): " + (latest.equals(inshops)));// (7) System.out.println(" latest == older: " + (latest == older)); // (8) System.out.println(" latest.equals(older): " + (latest.equals(older))); // (9) Object searchkey = inshops; System.out.println("Search key: " + searchkey); // (10) System.out.print("Array: "); for (int i = 0; i < versions.length; i++) // (11) System.out.print(versions[i] + " "); boolean found = false; for (int i = 0; i < versions.length &&!found; i++) found = searchkey.equals(versions[i]); // (12) System.out.println("\n Search key found in array: " + found); // (13) List vnolist = Arrays.asList(versions); // (14) System.out.println("List: " + vnolist); PGJC2E 11: Collections and Maps 11-7/33

System.out.println(" Search key contained in list: " + vnolist.contains(searchkey)); // (15) Map versionstatistics = new HashMap(); // (16) for (int i = 0; i < versions.length; i++) // (17) versionstatistics.put(versions[i], downloads[i]); System.out.println("Map: " + versionstatistics); // (18) System.out.println(" Hash code for keys in the map:"); for (int i = 0; i < versions.length; i++) // (19) System.out.println(" " + versions[i] + ": " + versions[i].hashcode()); System.out.println(" Search key " + searchkey + " has hash code: " + searchkey.hashcode()); // (20) System.out.println(" Map contains search key: " + versionstatistics.containskey(searchkey)); // (21) System.out.println("Sorted list:\n\t" + (new TreeSet(vnoList))); // (22) System.out.println("Sorted map:\n\t" + (new TreeMap(versionStatistics))); // (23) System.out.println("List before sorting: " + vnolist); // (24) Collections.sort(vnoList); System.out.println("List after sorting: " + vnolist); System.out.println("Binary search in list:"); // (25) int resultindex = Collections.binarySearch(vnoList, searchkey); System.out.println("\tKey: " + searchkey + "\tkey index: " + resultindex); PGJC2E 11: Collections and Maps 11-8/33

Output from the program: Test object reference and value equality: latest: (9.1.1), inshops: (9.1.1), older: (6.6.6) latest == inshops: false latest.equals(inshops): false latest == older: false latest.equals(older): false Search key: (9.1.1) Array: (3.49.1) (8.19.81) (2.48.28) (10.23.78) (9.1.1) Search key found in array: false List: [(3.49.1), (8.19.81), (2.48.28), (10.23.78), (9.1.1)] Search key contained in list: false Map: {(9.1.1)=123, (10.23.78)=1010, (8.19.81)=786, (3.49.1)=245, (2.48.28)=54 Hash code for keys in the map: (3.49.1): 13288040 (8.19.81): 27355241 (2.48.28): 30269696 (10.23.78): 24052850 (9.1.1): 26022015 Search key (9.1.1) has hash code: 20392474 Map contains search key: false Exception in thread "main" java.lang.classcastexception... PGJC2E 11: Collections and Maps 11-9/33

Implementing equals() method Equivalence relation: Reflexive: For any reference self, self.equals(self) is always true. Symmetric: For any references x and y, x.equals(y) is true if and only if y.equals(x) is true. Transitive: For any references x, y and z, if both x.equals(y) and y.equals(z) are true, then x.equals(z) is true. Consistent: For any references x and y, multiple invocations of x.equals(y) always return the same result, provided the objects denoted by these references have not been modified to affect the equals comparison. null comparison: For any non-null reference obj, obj.equals(null) is always false. The general contract of the equals() method is defined between objects of arbitrary classes. PGJC2E 11: Collections and Maps 11-10/33

Example 11.9 Implementing the equals() method public class UsableVNO { // Overrides equals(), but not hashcode(). private int release; private int revision; private int patch; public UsableVNO(int release, int revision, int patch) { this.release = release; this.revision = revision; this.patch = patch; public String tostring() { return "(" + release + "." + revision + "." + patch + ")"; public boolean equals(object obj) { // (1) if (obj == this) // (2) return true; if (!(obj instanceof UsableVNO)) // (3) return false; UsableVNO vno = (UsableVNO) obj; // (4) PGJC2E 11: Collections and Maps 11-11/33

return vno.patch == this.patch && // (5) vno.revision == this.revision && vno.release == this.release; PGJC2E 11: Collections and Maps 11-12/33

Checklist for implementing the equals() method See class UsableVNO in Example 11.9. Method overriding signature The method prototype is: public boolean equals(object obj) // (1) The signature of the method requires that the argument passed is of the type Object. The following header will overload the method, not override it: public boolean equals(myreftype obj) // Overloaded. Calls to overloaded methods are resolved at compile time, depending on the type of the argument. Calls to overridden methods are resolved at runtime, depending on the type of the actual object denoted by the argument. MyRefType ref1 = new MyRefType(); MyRefType ref2 = new MyRefType(); Object ref3 = ref2; boolean b1 = ref1.equals(ref2); // True. Calls equals() in MyRefType. boolean b2 = ref1.equals(ref3); // Always false. Calls equals() in Object. PGJC2E 11: Collections and Maps 11-13/33

Reflexivity test This is usually the first test performed in the equals() method, avoiding further computation if the test is true. if (obj == this) // (2) return true; Correct argument type The equals() method in Example 11.9 checks the type of the argument object at (3), using the instanceof operator: if (!(obj instanceof UsableVNO)) // (3) return false; The code above also does the null comparison correctly, returning false if the argument obj has the value null. The test at (3) can also be replaced by the following code in order to exclude all other objects, including subclass objects: if ((obj == null) (obj.getclass()!= this.getclass())) // (3a) return false; Argument casting The argument is only cast after checking that the cast will be successful: UsableVNO vno = (UsableVNO) obj; // (4) PGJC2E 11: Collections and Maps 11-14/33

Field Comparisons Equivalence comparison involves comparing certain fields from both objects to determine if their logical states match. For fields that are of primitive data types, their primitive values can be compared. return vno.patch == this.patch && // (5) vno.revision == this.revision && vno.release == this.release; If all field comparisons evaluate to true, the equals() method returns true. For fields that are references, the objects denotes by the references can be compared. (vno.productinfo == this.productinfo (this.productinfo!= null && this.productinfo.equals(vno.productinfo))) Exact comparison of floating-point values should not be done directly on the values, but on the integer values obtained from their bit patterns (see static methods Float.floatToIntBits() and Double.doubleToLongBits()). Only fields that have significance for the equivalence relation should be considered. The order in which the comparisons are carried out can influence the performance of the equals comparison. PGJC2E 11: Collections and Maps 11-15/33

Using the UsableVNO class See class TestVersionUsable in Example 11.10 which uses objects of the class UsableVNO. Test object value equality. Object value equality is compared correctly as defined by the equals() method. Test searching in an array. Search in the versions array works correctly according to the overridden equals() method. Test for membership in a collection. Membership in the versions array works correctly according to the overridden equals() method. Test for membership in a map. The result is always false as the hashcode() method is not overridden. Test for usage in a sorted collection and map. Exception thrown as the compareto() method of the Comparable interface is not implemented. PGJC2E 11: Collections and Maps 11-16/33

Example 11.10 Implications of overriding the equals() method public class TestVersionUsable extends TestVersionSimple { public static void main(string[] args) { (new TestVersionUsable()).test(); protected Object makeversion(int a, int b, int c) { return new UsableVNO(a, b, c); Output from the program: Test object reference and value equality: latest: (9.1.1), inshops: (9.1.1), older: (6.6.6) latest == inshops: false latest.equals(inshops): true latest == older: false latest.equals(older): false Search key: (9.1.1) Array: (3.49.1) (8.19.81) (2.48.28) (10.23.78) (9.1.1) Search key found in array: true List: [(3.49.1), (8.19.81), (2.48.28), (10.23.78), (9.1.1)] Search key contained in list: true Map: {(10.23.78)=1010, (2.48.28)=54, (3.49.1)=245, (9.1.1)=123, (8.19.81)=786 Hash code for keys in the map: PGJC2E 11: Collections and Maps 11-17/33

(3.49.1): 27355241 (8.19.81): 30269696 (2.48.28): 24052850 (10.23.78): 26022015 (9.1.1): 3541984 Search key (9.1.1) has hash code: 11352996 Map contains search key: false Exception in thread "main" java.lang.classcastexception... PGJC2E 11: Collections and Maps 11-18/33

Hashing Hashing is an efficient technique for storing and retrieving data. A common hashing scheme uses an array, where each element is a list of items. The array elements are called buckets. Converting an item to its array index is done by a hash function. The array index returned by the hash function is called the hash value of the item. Storing an item involves the following steps: 1. Hashing the item to determine the bucket. 2. If the item does not match one already in the bucket, it is stored in the bucket. Note that no duplicate items are stored. Retrieving an item is based on using a key. The key represents the identify the item. Item retrieval is also a two-step process: 1. Hashing the key to determine the bucket. 2. If the key matches an item in the bucket, this item is retrieved from the bucket. Different items can hash to the same bucket, meaning that the hash function returns the same hash value for these items: collisions. Finding an item in the bucket can entail a search, and requires an equality function to compare items. PGJC2E 11: Collections and Maps 11-19/33

An ideal hash function produces a uniform distribution of hash values for a collection of items across all possible hash values. Not an easy task to design adequate hash functions, but fortunately, there are heuristics. PGJC2E 11: Collections and Maps 11-20/33

The hashcode() method A hash table contains key-value entries as items, and the hashing is done only on the keys to provide efficient lookup of values. Matching a given key with a key in an entry, determines the value. To use hash-based collections and maps of the java.util package, the class must provide appropriate implementations of the following methods from the Object class: A hashcode() method that produces hash values for the objects. An equals() method that tests objects for equality. General rule: a class which overrides the equals() method must override the hashcode() method. The class UsableVNO violates the key tenet of the hashcode() contract: equal objects must produce equal hash codes. PGJC2E 11: Collections and Maps 11-21/33

General Contract of the hashcode() Method Consistency during execution. Object value equality implies hash value equality. Object value inequality places no restrictions on the hash value. Note that the hash contract does not imply that objects with equal hash codes are equal. Not producing unequal hash codes for unequal objects can have an adverse effect on performance, as unequal objects will hash to the same bucket. PGJC2E 11: Collections and Maps 11-22/33

Example 11.11 Implementing the hashcode() method public class ReliableVNO { // Overrides both equals() and hashcode(). private int release; private int revision; private int patch; public ReliableVNO(int release, int revision, int patch) { this.release = release; this.revision = revision; this.patch = patch; public String tostring() { return "(" + release + "." + revision + "." + patch + ")"; public boolean equals(object obj) { // (1) if (obj == this) // (2) return true; if (!(obj instanceof ReliableVNO)) // (3) return false; ReliableVNO vno = (ReliableVNO) obj; // (4) PGJC2E 11: Collections and Maps 11-23/33

return vno.patch == this.patch && // (5) vno.revision == this.revision && vno.release == this.release; public int hashcode() { // (6) int hashvalue = 11; hashvalue = 31 * hashvalue + release; hashvalue = 31 * hashvalue + revision; hashvalue = 31 * hashvalue + patch; return hashvalue; PGJC2E 11: Collections and Maps 11-24/33

Heuristics for implementing the hashcode() Method In Example 11.11, the hash value is computed according to the following formula: hashvalue = 11 * 31 3 + release * 31 2 + revision * 31 1 + patch Each significant field is included in the computation. This ensures that objects which are equal according to the equals() method, also have equal hash values according to the hashcode() method. The basic idea is to compute an int hash value sfval for each significant field sf, and include an assignment of the form shown at (1) in the computation: public int hashcode() { int sfval; int hashvalue = 11;... sfval =... // Compute hash value for each significant field sf. hashvalue = 31 * hashvalue + sfval; // (1)... return hashvalue; PGJC2E 11: Collections and Maps 11-25/33

Calculating the hash value sfval for a significant field sf depends on the type of the field: Field sf is boolean: sfval = sf? 0 : 1 Field sf is byte, char, short, or int: sfval = (int)sf Field sf is long: sfval = (int) (sf ^ (sf >>> 32)) Field sf is float: sfval = Float.floatToInt(sf) Field sf is double: long sfvaltemp = Double.doubleToLong(sf); sfval = (int) (sfvaltemp ^ (sfvaltemp >>> 32)) Field sf is a reference that denotes an object. Typically, the hashcode() method is invoked recursively if the equals() method is invoked recursively: sfval = ( sf == null? 0 : sf.hashcode()) Field sf is an array. Contribution from each element is calculated similarly to a field. The order in which the fields are incorporated into the hash code computation will influence the hash value. A legal or correct hash function does not necessarily mean it is appropriate or efficient. public int hashcode() { return 1949; PGJC2E 11: Collections and Maps 11-26/33

Example 11.12 Implications of overriding the hashcode() method public class TestVersionReliable extends TestVersionSimple { public static void main(string[] args) { (new TestVersionReliable()).test(); protected Object makeversion(int a, int b, int c) { return new ReliableVNO(a, b, c); Output from the program:... Map: {(10.23.78)=1010, (2.48.28)=54, (3.49.1)=245, (8.19.81)=786, (9.1.1)=123 Hash code for keys in the map: (3.49.1): 332104 (8.19.81): 336059 (2.48.28): 331139 (10.23.78): 338102 (9.1.1): 336382 Search key (9.1.1) has hash code: 336382 Map contains search key: true Exception in thread "main" java.lang.classcastexception... PGJC2E 11: Collections and Maps 11-27/33

The compareto() method This method defines the natural ordering for the instances of a class. Objects implementing Comparable can be used in sorted collections and sorted maps. public interface Comparable<T> { int compareto(t o); The method returns a negative integer, zero or a positive integer if the current object is less than, equal to or greater than the specified object, based on the natural order. It throws a ClassCastException if the reference value passed in the argument cannot be cast to the type of the current object. PGJC2E 11: Collections and Maps 11-28/33

Criteria for implementing the compareto() method: For any two objects of the class, if the first object is less than, equal to or greater than the second object, then the second object must be greater than, equal to or less than the first object, respectively. All three order comparison relations (less than, equal to, greater than) embodied in the compareto() method must be transitive. For any two objects of the class, which compare as equal, the compareto() method must return the same results if these two objects are compared with any other object. The compareto() method must be consistent with equals. The magnitude of non-zero values returned by the method is immaterial; the sign indicates the result of the comparison. Example 11.13 Implementing the compareto() method of the Comparable interface public final class VersionNumber implements Comparable<VersionNumber> { private final int release; private final int revision; private final int patch; public VersionNumber(int release, int revision, int patch) { PGJC2E 11: Collections and Maps 11-29/33

this.release = release; this.revision = revision; this.patch = patch; public String tostring() { return "(" + release + "." + revision + "." + patch + ")"; public boolean equals(object obj) { // (1) if (this == obj) // (2) return true; if (!(obj instanceof VersionNumber)) // (3) return false; VersionNumber vno = (VersionNumber) obj; // (4) return vno.patch == this.patch && // (5) vno.revision == this.revision && vno.release == this.release; public int hashcode() { // (6) int hashvalue = 11; hashvalue = 31 * hashvalue + release; hashvalue = 31 * hashvalue + revision; hashvalue = 31 * hashvalue + patch; return hashvalue; PGJC2E 11: Collections and Maps 11-30/33

public int compareto(versionnumber vno2) { // (7) if (this == vno2) // (8) return 0; // Compare the release numbers. (9) if (release < vno2.release) return -1; if (release > vno2.release) return 1; // Release numbers are equal, (10) // must compare revision numbers. if (revision < vno2.revision) return -1; if (revision > vno2.revision) return 1; // Release and revision numbers are equal, (11) // must compare patch numbers. if (patch < vno2.patch) return -1; if (patch > vno2.patch) return 1; // All fields are equal. (12) return 0; PGJC2E 11: Collections and Maps 11-31/33

A null argument should result in a NullPointerException. The fields are compared with the most significant field first and the least significant field last. Significant fields with non-boolean primitive values are normally compared using the relational operators < and >. For comparing significant fields denoting constituent objects, the main options are to invoke the compareto() method on them, or to use a comparator. The equals() implementation can call the compareto() method. public boolean equals(object other) { //... return compareto((versionnumber)other) == 0; // Note the cast. PGJC2E 11: Collections and Maps 11-32/33

Example 11.14 Implications of implementing the compareto() method public class TestVersion extends TestVersionSimple { public static void main(string[] args) { (new TestVersion()).test(); protected Object makeversion(int a, int b, int c) { return new VersionNumber(a, b, c); Output from the program:... Sorted list: [(2.48.28), (3.49.1), (8.19.81), (9.1.1), (10.23.78)] Sorted map: {(2.48.28)=54, (3.49.1)=245, (8.19.81)=786, (9.1.1)=123, (10.23.78)=1010... PGJC2E 11: Collections and Maps 11-33/33