For performance. It cut the start-up time of the STEP Server in 2 and think it would help mobile platforms even more when many modules are on disk.

The reason is: 

for (int j = 0; j < dirs.length; j++) {
            getBooks(valid, dirs[j]);
        }

iterates through every book in the set loaded so far. That method calls:  if (!valid.contains(book)) {
                     under the next getBooks() call.

As a result for a list, it was getting proportionally longer as the books were loaded.

If hashcode() is not unique, it will cause problems in other areas that we've had (I had to fix a bug elsewhere where the hashcode() was not unique and books were used in a Map (I think Martin committed that fix before me).