Tuesday 30 July 2013

Mis-Using Abstract for Static Classes

Recently came across this construction in the code we have at work.


Now, some notes:

  • nowhere was a subclass defined to implement the 'abstract methods' in StringUtilities.
  • as a matter of fact, there were no 'abstract methods'.
  • all other methods were defined 'static'

It seemed a weird way to defeat instantiation (badly, by the way, as a person could simply subclass the thing and instantiate that).

Proper defeating of instantiation is done by means of a private constructor.


But, if what you need is a Singleton, perhaps it's better to just define a single ENUM.

Nobody could quite explain to me in which cases the first example would be a "Good Idea"™.

Tuesday 23 July 2013

Examples of a HashSet

Introduction


Some Real Life Examples where we use a Hash and Buckets.

Let me first shortly introduce how a hash works by means of the first example, an AddressBook, and as a followup how it is implemented in Java's HashSet.

Addressbook


A HashSet is a specific implementation of a Set. It uses the Hash of the stored objects to determine the position in an array of what are called Buckets. Every bucket in the array is, if filled, filled with another collection. So a HashSet is actually a collection of collections.

Let's see some examples of hashes people use when finding addresses in an AddressBook:
perfect hash: returns number in a numeral system with radix 26
in this case each name in the address book has a unique hashcode. Every list contains exactly one entry. If you use this as an address book, each page contains at most one address. You are going to need a huge amount of pages, if you have a lot of friends and relatives. With this behaviour it would make more sense to store addresses via a key-value store (for example an implementation of Map).
average hash: return first letter of the last name, capitalised
in this case, the behaviour is the same as your average normal address book. Each list contains all address of people whos names start with the same letter.
bad hash: return 'A'
in this case, the behaviour is terrible! You could compare it to an address book, on which all addresses are written on the first page. This way, the hashset will behave like a normal linked list.
Let's assume the hash used is the middle one. The Hashcode of entries in an AddressBook takes the first letter of the last name (capitalised).


Java's HashSet

We assume a class Address, containing the hashCode() method that returns the first letter of the last name.


The HashSet<Address> is implemented by using a HashMap<Address, Object> internally.

Now, the HashMap has an underlying data structure consisting of a Entry<Address, Object>[] table. This is the array that is going to contain all the first elements of each linked list. In other words, this is the Array containing the buckets.


The index of a bucket in the array is almost equivalent to the hashCode of the Address instance.

When I say almost, I mean that some additional conversions take place on the original hashCode, for instance:
  • In the case of using Strings Sun (Oracle?) uses a special hashing function (sometimes)
  • Some bit twiddling takes place to prevent collisions due to hashCodes that do not use lower bits, and therefore would cause the start of the bucket array to never be used.
  • The result is "binary and"ed, ofcourse, with the table length (which is always a power of two) as a quick sort of modulo function to prevent ArrayIndexOutOfBounds problems.

For this reason, the buckets are not at the positions in the bucket array as you would expect, given the answers of the hashCode() function.

Every bucket contains the first Entry (Entry<Address, Object>) of a linked list.

A new entry is added to the top of the Linked list.

Where each Entry has a pointer to the next Entry in the bucket, or null if it is the only or last entry, effectively creating/ending the linked list.

So the contents should look like follows:

Supermarket


The Hashcode used in a supermarket is infinitely worse than my Addressbook. To start a search, accost an employee of said supermarket and inquire after the location of an article, say washing detergent. You'll receive the hashcode "aisle 14" or some such. When at the location of said hashbucket, you find all articles jumbled together. Your senses assailed by every colour swirl, bubble and geometric shape imaginable with letters and numbers in wild and disturbing images.

If you are lucky, the hashcode is maginally improved with additional information like "on the left", or "at the very end".

Conclusion


Apparently, in real life, there are HashSets in use as well. We can only come to the conclusion that any logical data structure that we use in real life without thinking, has it's corresponding implementation in the Software Realm.

I hope you've enjoyed this journey of discovery into the Java source code, as much as I did.

References

Why always override hashcode() if overriding equals()?
http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20
Java 6 HashMap JavaDoc
http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html
Java 6 HashSet JavaDoc
http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html
Java Generics and Collections
Maurice Naftalin & Philip Wadler

Tuesday 16 July 2013

Formula

The Formula annotation is used on a property of a Hibernate entity. It is currently not a part of the Java Persistence Standard, and thusly is a Hibernate extension.

I thought I'd write some of my notes and bookmarks to other sites here, as the information in the Hibernate book seems very brief.


Advantages

  • the SQL in the formula is inserted automatically whenever you retrieve the Entity, without you having to think about it.
  • the advantage compared to calculating the fields in the Getter or Setter, is that it is possible to use the property in HQL queries. For example, adding "ORDER BY existsFreeby" in HQL without problems.

Disadvantages

  • HQL cannot be used in the Formula.
  • you have plain SQL in your Entity. I know this is normal according to the JPA spec, but at work they tend to frown on that. Don't ask me why.
  • whenever a keyword is unknown, it will prefix it with the name of the Entity table. This is a good feature, normally. In the example give, for example, the "id" will be expanded to "ORDERS0_.id". However, in the case where we used COALESCE, if we had a space between COALESCE and the opening bracket, like so "COALESCE (", Hibernate would expand this to "ORDERS0_.COALESCE (" causing an error, obviously.
  • a problem can occur when you are using ansi sql queries and using query.addEntity(Orders.class); It will break on that now.

Note

Always use opening and closing brackets at the beginning and end of the actual SQL part. As it is inserted into the Hibernate created SQL, it might break the syntax if you forget.

References

2.4.3.1. Formula
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
Hibernate derived properties
http://blog.eyallupu.com/2009/07/hibernate-derived-properties.html
Calculated property with JPA / Hibernate
http://stackoverflow.com/questions/2986318/calculated-property-with-jpa-hibernate
@Formula adds a this_. prefix to an SQL function - Hibernate HH-5265
https://hibernate.atlassian.net/browse/HHH-5265
Hibernate with JPA ignoring @Formula
http://stackoverflow.com/questions/7824805/hibernate-with-jpa-ignoring-formula

Tuesday 9 July 2013

Java Persistence with Hibernate, Second Edition

Recently bought "Java Persistence with Hibernate, Second Edition" from Manning Publications Co. It contains Hibernate 5 in detail along with the Java Persistence 2.1 standard (JSR 338).

It's the first time for me to try out MEAP, Manning's Early Access Program. I can read chapters as they are written.

Once the book is finished, I get the dead-tree-copy in the mail.

So far, I'm rather pleased.

Tuesday 2 July 2013

Properly Accessing your Outer Class

Recently, during my work, a colleague indicated a way to make it obvious that a variable used in an Inner class, belonged to the outer class. In order to prevent being ambiguous.


I didn't know that could work.

References

Nested Classes - The Java Tutorials
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html