> My Java Aquarium ***

Friday, April 16, 2010

playing around equals() and hashCode() methods of Object class

Why, when & how of overriding equals() and hashCode() methods of Object class

As we know the Object class has five non final methods namely equals, hashCode, toString, clone, and finalize.
I believe they were primarily designed to be overridden according to specific needs.
I am just trying to summarize my understanding around these two methods. When should we override these and how we should implement these etc. Any comments/discussion/feedback would be highly appreciated on above topics.

Overriding the equals method -
Ideally you should override the equals method when you want to specify the rules of logical equality of objects. Two objects are logically equal if they have the same values for the same uniqueness attributes.

We need to implement an equivalence relation between non null object references. The rules to override equals method can be found on sun's site. They basically talk about Symmetry , Reflectivity Consistency & Transitivity among the objects.

The rule for the null reference is that any non-null reference value x, x.equals(null) must return false.

Object class already provides an implementation of the equals method. It is
public boolean equals(Object obj) {
return (this == obj);
}

The method above simply tests for equality of object references. This is not always the desired behavior, particularly when comparing Strings. That's why the String class provides its own implementation of the equals method.

For example suppose we have a Student class which has a constructor like this.
public Student(String name, String id, int age) { …}

Now if you create two student objects with the same attributes, you'd want those two objects to be the same student. If you write a code like below then you will get false as result.

Student student1 = new Student("sajid", "456789", 28);
Student student2 = new Student("sajid", "456789", 28);
System.out.println(student1.equals(student2));

Result is false because student1 and student2 are different references and the equals method being used here (from the object class) is comparing references. So here we need to override the equals method to check for our uniqueness attributes for our comparisons to work.

Caution: we should not do a mistake of overloading the equals method instead of overriding it. So the argument to the equals method must be an Object.

See the difference between below two statements. You will understand it.
public boolean equals(Object obj)
public boolean equals(Student student)

A good implementation of equals should start with symmetry test. Means x.equals(x) should always return true. If this it self is failing then no need to proceed further.

Another important point would be to test the instance of the object passed to equals() method. People might pass a String object instead of Object in the argument. Here instanceof operator helps us to check this.

instanceof also eliminates the trivial cases when the object passed is null because it returns false if the first argument is null.

So whole implementation might look like this …

public boolean equals(Object obj) {
if (this == obj) {
return true;
}

if ( !(obj instanceof Student)) {
return false;
}

Student student = (Student)obj;
return age == student.getAge() && name.equals(student.getName())
&& id.equals(student.getId());

}

Now System.out.println(student1.equals(student2)); will print true.

Food for thought -
Note that we deliberately compared the ages (integers) first. The && operator has short circuit behavior, meaning that if the age comparison fails the rest of the comparison is abandoned and false is returned. It is therefore a performance advantage to have the cheaper (memory wise) tests first and the more memory demanding tests last.

Is there any situation when we should not override equals() ?
Yes. When the references check is sufficient. This is when each instance of the class is unique. Other situation could be when parent class already has implemented the desired behavior then we need not bother.

Now whenever we override the equals method, we must also override the hashCode method.
So let's move ahead to hashing …


Overriding the hashCode method -
Why hashcode ? Simple the hashCode method is supported for the benefit of hash based collections. Basically this hash code value is used by hash based collections such as Hashtable, HashMap, HashSet, etc. for storing, retrieving, sorting, and other data structure operations.

The contract says that If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. It also says that the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.

It further says that It is not required that if two objects are unequal according to the equals method, then calling the hashCode method on each of the two objects must produce distinct integer results.

So equal objects must have equal hashCodes. An easy way to ensure that this condition is always satisfied is to use the same attributes used in determining equality in determining the hashCode. Now we should realize why it is important to override hashCode every time we override equals.

The story of hashtable and buckets .. (Some useful history) -
we can think a hash table as a group of buckets. When you add a key-value pair, the key's hashCode is used to determine which bucket to put the mapping.
Similarly when you call the get method with a key on the hash table, the key's hashCode is used to determine in which bucket the mapping was stored. This is the bucket that is searched (sequentially) for the mapping.
If you have two "equal" objects but with different hashCodes, then the hash table will see them as different objects and put them in different buckets. Similarly you can only retrieve an object from a hash table by passing an object with the same hashCode as the object you are trying to retrieve. If no matching hashCode is found, null is returned.
So let's say it again, "Equal objects must have equal hashCodes".

The best hashcode approach -
We should try to make all unequal objects have unequal hashCodes. This means each mapping is stored in its own bucket. This is the optimal case for the hash table and results in linear search times because only the correct bucket needs to be searched for. Once the correct bucket is found, the search is complete. That's why the API docs said

"However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables."

How do I implement hashCode ?
Well we want it to be linked to the equals method in some way and so it must use the same attributes as the equals method.

The hashCode method signature in Object class is -
public native int hashCode();

The key thing to note here is that the method returns an integer. This means that we should try to get an integer representation of all the attributes that were used to determine equality in the equals method. The trick is that we should get this integer representation in a way that ensures that we always get the same int value for the same attribute value.
Once we have the integers, it's up to us to find a way of combining them into one integer that represents the hashCode for our object.

Whatever algorithm we use, we must make sure that the result is always an integer and will be the same integer returned for equal objects.
So how do we determine the hashCodes for the attributes themselves?

For the individual attributes values, you can use the following popular approach
(Source: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods )
  • For boolean variables use 0 if it's true and 1 if it's false.
  • Converting byte, char or short to int is easy. Just cast to int. The result is always the same for the same value of the attribute.
  • A long is bigger than an int. You can use (int)value^(value >>> 32) . This is the method used by the java.lang.Long class.
  • If the field is a float, use Float.floatToIntBits(value).
  • If the field is a double, use Double.doubleToLongBits(value), and then hash the resulting long using the method above for long type.
  • If the field is an object reference and this class's equals method compares the field by recursively invoking equals, then recursively invoke hashCode on the field as well.
  • If the value of the field is null, return 0 (or some other constant, 0 is more common but you might want to distinguish it from the boolean case).
  • Finally, if the field is an array, go through each element and compute each element's hashCode value. Use the sum of the hashCodes as the hashCode for the array attribute.

Let's look at some ways of doing it.
A common approach is to choose a multiplier, say p, and then compute an int value by applying the following formula
hashCode = multiplier * hashCode + attribute's hashCode for all the attributes.

For three atributes (a1, a2, a3), the hashCode would be computed in the following steps
hashCode = multiplier * hashCode + a1's hashCode //step 1
hashCode = multiplier * hashCode + a2's hashCode //step 2
hashCode = multiplier * hashCode + a3's hashCode //step 3

Now putting it all together our Student class will look like this. .

public class Student {
String id;
String name;
int age;
private volatile int hashCode = 0;

public Student(String name , String id, int age) {
this.name = name;
this.id = id;
this.age = age;
}

String getName() {
return name;
}

int getAge() {
return age;
}

String getId() {
return id;
}

public boolean equals(Object obj) {
if(this == obj) {
return true;
}
if (!(obj instanceof Student)) {
return false;
}
Student student = (Student)obj;
return age == student.getAge() && name.equals(student.getName())
&& id.equals(student.getId());

}

public int hashCode () {
final int multiplier = 23; // we should use any prime number here like 23 or 31 etc
if (hashCode == 0) {
int code = 133;
code = multiplier * code + age;
code = multiplier * code + id.hashCode();
code = multiplier * code + name.hashCode();
hashCode = code;
}
return hashCode;
}

}

To test we can use a main() method in the above class like this -

public static void main(String args[]){
Student student1 = new Student("sajid", "456789", 28);
Student student2 = new Student("sajid", "456789", 28);
System.out.println(student1.equals(student2)); // prints true
}

Another way to implement hashCode would be
Similar to how we implemented hashCode our hash code calculation must involve all attributes of the class that contribute to the equality comparison of the class. For Car class example, the following would work:
public int hashCode()
{
int hash = 7;
hash = 31 * hash +
(null == this.licensePlate ? 0 : this.licensePlate.hashCode());
hash = 31 * hash +
(null == this.vinNumber ? 0 : this.vinNumber.hashCode());

return hash;
}

Java provides an implementation of hashCode for built-in classes such as String and other wrapper classes. If you have an int data type that is part of your equals comparison you can simply add, subtract, multiply, or divide it into your hash code value.
Several APIs demand that the user must implement the hashCode() method. The reason is that these APIs are using hash based containers (like HashMap) to have a fast means of managing lots of objects (always comparing objects using equals() would need endless time).

I will try to further dig into the internals of hashing and difference between different hash based collections and the best performance strategies around it.

Labels: ,

Tuesday, December 22, 2009

Signed Applet and how to make a signed jar

A signed Applet is a trusted Applet (applet will reside inside a jar). In order to get access to the file system all jar files in an application must be signed. By default for security reasons, Java applets are contained within a sandbox.

This means that the applets can’t do anything, which might be threatening to the user’s machine (e.g. reading, writing or deleting local files, putting up message windows, or querying various system parameters).

Early browsers had no provisions for Java applets to reach outside of the sandbox. Recent browsers, however have provisions to give “trusted” applets the ability to work outside the sandbox. For this power to be granted to one of your applets, the applet’s code must be digitally signed with your unforgettable digital ID, and then the user must state that he trusts applets signed with your ID. The mistrusted applet can request to have privileges outside the sand box but will have to request the user for privileges every time it executes. But with the trusted applet the user can choose to remember their answer to the request, which means they won’t be asked again.

Let’s see what it takes to create your own signed applets. There are few tools given by Sun to create your own signed applets. It mainly comprise of three main steps.

(1) First step is generating a keypair with the keytool.

D:/j2sdk1.5/bin/keytool -genkey -alias green -keypass greenpass

green is the alias for the keypair, and greenpass is the password to access that alias(or keypair). The keypair
will be stored in the file .keystore in your homedirectory unless you specify otherwise.
You'll be asked a lot of questions, you may lie or just hit enter!

(2) Create a self-signed certificate.

D:/j2sdk1.5/bin/keytool -selfcert -alias green

(3) After the keypair has been generated the jar file can be signed with jarsigner.

jarsigner YourJarFileName alias

d:/j2sdk1.5/bin/jarsigner Test.jar green
It will ask for both passwords specified while generating the keys.

The jar file has now been signed. Now you can distribute this jar file to anyone or it can run on any system with the privilege to access your file system.

Note: this signature is only valid for 6 months. After that it will expire so you probably need to sign it again after 6 months.

Labels: ,

Tuesday, November 3, 2009

New features in Java 6.0 (Mustang)

In this Java release SUN has not done much changes at language level rather major enhancement is done in core, XML and desktop sections.

Any feature or enhancement in Java is encapsulated in the form of a JSR (Java Specification Request) which details the need for a specific functionality to be available in the Java Platform that can be used by Applications. These JSR's will be reviewed and released by Java Expert Groups (JEG).

Following the major list of features (JSRs') that comes with the Java 6.0.
  • Java Compiler API (JSR 199)
  • JDBC 4.0 (JSR 221)
  • Scripting in the Java Platform (JSR 223)
  • Pluggable Annotation Processing API (JSR 269)
  • Common Annotations (JSR 250)
  • Java API for XML Based Web Services - 2.0 (JSR 224)
  • JAXB 2.0 (JSR 222)
  • Web Services Metadata (JSR 181)
  • Streaming API for XML (JSR 173)
  • XML Digital Signature (JSR 105)
  • Java Class File Specification Update (JSR 202)

I will try to explore and explain each of these JSR's in my future articles.
The latest java 6.0 can be downloaded from here. I am really excited about scripting framework, scripting API and new JDBC 4.0 API in this release.


List of top 10 features in Java SE 6.0 adapted from SUN's site

Web Services
You get first-class support for writing XML web service client applications (death of Apache Axis?). No more messing with the plumbing (unless you really want to). You can also expose your APIs as .NET interoperable web services with a simple annotation.
For developers who want to handle XML directly Mustang adds new parsing and XML to Java object-mapping APIs, previously only available in Java EE platform implementations or the Java Web Services Pack.

Scripting
You can now mix in JavaScript technology with your Java technology source code, useful for prototyping. Also useful when you have teams with a variety of skill sets.

Database
The final Mustang development kit will co-bundle the all-Java JDBC database, Java DB based on Apache Derby. This should enable developers (new to Java) to get a jumpstart on java development.
Developers will get the updated JDBC 4.0, which focuses on ease of use. It contains many feature additions like support for XML as an SQL datatype and better integration of Binary Large OBjects (BLOBs) and Character Large OBjects (CLOBs) into the APIs. Additional features that improve ease of use include removal of some JDBC boilerplate and some of the new annotations that make SQL strings embed better into your JDBC application - like decorating your getAllUsers() method with an @Query(sql="select * from user") annotation, and that being all you need. More annotation love for you.

More Desktop APIs
GUI developers get a large number of new tricks to play like the ever popular yet newly incorporated SwingWorker utility to help you with threading in GUI apps, JTable sorting and filtering, and a new facility for quick splash screens to quiet impatient users.

Monitoring and Management
The really big deal here is that you don't need do anything special to the startup to be able to attach on demand with any of the monitoring and management tools in the Java SE platform. Mustang adds yet more diagnostic information, and we co-bundled the infamous memory-heap analysis tool Jhat for forensic explorations of those core dumps.

Compiler Access
Really aimed at people who create tools for Java development and for frameworks like JavaServer Pages (JSP) or Personal Home Page construction kit (PHP) engines that need to generate a bunch of classes on demand, the compiler API opens up programmatic access to javac for in-process compilation of dynamically generated Java code. Finally you don't have to save your code as a Java files and invoke javac to generate a classfile, a clumsy procedure at best.

Pluggable Annotations
Java tool and framework vendors (and you) can define annotations and have core API support for plugging in and executing the processors that do the heavy lifting. It seamlessly integrates your custom annotations .

Desktop Deployment
Better platform look-and-feel in Swing technology, LCD text rendering (more clarity on LCD monitors like Vista), and snappier GUI performance overall. Java applications can integrate better with the native platform with things like new access to the platform's System Tray and Start menu. At long last, Mustang unifies the Java Plug-in technology and Java WebStart engines, which just makes sense. Installation of the Java WebStart application got a much needed makeover.

Security
Mustang simplified the job of security administrators by providing various new ways to access platform-native security services, such as native Public Key Infrastructure (PKI) and cryptographic services on Microsoft Windows for secure authentication and communication, Java Generic Security Services (Java GSS) and Kerberos services for authentication, and access to LDAP servers for authenticating users.

Quality, Compatibility, Stability
Sun has around 80,000 test cases and several million lines of code testing conformance. People have been downloading (and testing) snapshots of Mustang for the last 15 months and filing bugs. So even before beta several quality and regression issues were fixed. Performance is claimed to be better than J2SE 5.

Labels: , ,

Tuesday, October 21, 2008

My understanding of Factory Pattern

Going by definition Factory pattern is a creational design pattern used in software development to encapsulate the processes involved in the creation of objects.

In simple terms we can say that factory pattern is a good choice when we need to create object depending on some parameter at runtime.

Let’s say if we have a super class and sub-classes, and based on data provided (any parameter), we have to return the object of one of the sub-classes, then factory pattern is the ideal choice.

Lets take a simple example to understand its working..

Suppose we have an application which stores Customer details like name and sex etc. Depending on sex the application will create either a male or a female object and accordingly print a hello message.

public class Customer {

public String name;

//gender : M or F

private String gender;

public String getName() {

return name;

}

public String getGender() {

return gender;

}

}

Customer class is having methods for name and gender. And the sub classes will print hello message as shown below.

public class Male extends Customer {

public Male(String name) {

System.out.println("Hello Mr. "+name);

}

}

public class Female extends Customer {

public Female(String name) {

System.out.println("Hello Ms. "+name);

}

}

Now create a client, called CustomerFactory which will return Male or Female object depending on the data provided

public class CustomerFactory {

public static void main(String args[]) {

CustomerFactory factory = new CustomerFactory();

factory.getCustomer(args[0], args[1]);

}

public Customer getCustomer(String name, String gender) {

if (gender.equals("M"))

return new Male(name);

else if(gender.equals("F"))

return new Female(name);

else

return null;

}

}

On compiling and running this client program..

Java CustomerFactory Sarah F

The output is: “Hello Ms. Sarah”.

Now let’s summarize when to use Factory Pattern

· When a class does not know which class of objects it must create.

· When we want to encapsulate the process of creating the objects.

· When we have to create an object of any one of sub-classes depending on the data provided.

So now its time to create your own factories as you wish J

Labels: ,

Friday, October 10, 2008

Comparing object and sorting them in java using Comparator and Comparable interfaces

As we know sorting is one of the very common tasks especially when we have a list or collection of objects. For example if we have a list of Employees then we would like to display it in some order may be by sorting them by EmpId or name. In these situations both (Comparator and Comparable) will become handy.

About Comparators and Comparables

Simply putting java.lang.Comparator and java.lang.Comparable are used for comparing objects in java.

Comparator

A comparator object is capable of comparing two different objects. The class is not comparing its instances, but some other class’s instances. This comparator class must implement the java.lang.Comparator interface.

Comparable

A comparable object is capable of comparing itself with another object. The class itself must implements the java.lang.Comparable interface in order to be able to compare its instances.

Now lets see how we can use these interfaces

Each of these has one method to be implemented by user.

java.lang.Comparable: int compareTo(Object obj1)
This method compares this object with obj1 object. Returned int value has the following meanings.

  1. positive – this object is greater than obj1
  2. zero – this object equals to obj1
  3. negative – this object is less than obj1


java.lang.Comparator: int compare(Object obj1, Object obj2)
This method compares obj1 and obj2 objects. Returned int value has the following meanings.

  1. positive – obj1 is greater than obj2
  2. zero – obj1 equals to obj2
  3. negative – obj1 is less than obj1

Note:

java.util.Collections.sort(List) and java.util.Arrays.sort(Object[]) methods can be used to sort using natural ordering of objects.
java.util.Collections.sort(List, Comparator) and java.util.Arrays.sort(Object[], Comparator) methods can be used if a Comparator is available for comparison.

Now let’s do a simple example to see these concepts in real scenario.

(1) First we will write a simple Employee class as below..

public class Employee {

private int empId;

private String name;

public Employee(int empId, String name) {

this.empId=empId;

this.name=name;

}

public int getEmpId() {

return empId;

}

public void setEmpId(int empId) {

this.empId = empId;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

(2) Next we will write a class to implement compare() method of comparator interface. You can see below in the code that we are comparing Employee object by name attribute. Instead of name we can use Empid attribute to compare objects for sorting. The choice depends on the need.

public class NameComparator implements Comparator{

public int compare(Object emp1, Object emp2) {

String emp1Name = ( (Employee) emp1).getName();

String emp2Name = ( (Employee) emp2).getName();

return emp1Name.compareTo(emp2Name);

}

}

(3) Finally we will write a test class to use our NameComparator class for comparing and sorting Employee objects.

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashSet;

import java.util.Iterator;

import java.util.List;

import java.util.Set;

public class TestEmployeeSort {

public static void main(String args[]){

//create a set of Employee object without any specific order

Set<Employee> set = new HashSet<Employee>();

set.add(new Employee(3, "Raj"));

set.add(new Employee(1, "Sajid"));

set.add(new Employee(6, "Sowmya"));

set.add(new Employee(2, "Manu"));

set.add(new Employee(7, "Larry"));

set.add(new Employee(4, "Suresh" ));

set.add(new Employee(8, "Harry"));

set.add(new Employee(5, "Ashu"));

//converting set to list

List<Employee> list=new ArrayList<Employee>(set);

System.out.println("Order of employee before sorting is");

Iterator i=list.iterator();

while(i.hasNext())

{

Employee e1=(Employee) i.next();

System.out.println(e1.getEmpId() + "\t" + e1.getName() );

}

//calling sort method and passing the list of employees and a new instance of our NameComparator class

Collections.sort(list,new NameComparator());

System.out.println("Order of employee after sorting is");

for (Employee e: list) {

System.out.println(e.getEmpId() + "\t" + e.getName() );

}

}

}

After running this test class we would get following output.

Order of employee before sorting is

3 Raj

8 Harry

6 Sowmya

1 Sajid

4 Suresh

5 Ashu

7 Larry

2 Manu

Order of employee after sorting is

5 Ashu

8 Harry

7 Larry

2 Manu

3 Raj

1 Sajid

6 Sowmya

4 Suresh

Labels: