Java
hashCode
String
multiplier
31

Why does Java's hashCode in String use 31 as a multiplier?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Java, the hashCode() method plays a critical role in the management and efficiency of hash-based collections such as HashMap, HashSet, and Hashtable. The hashCode() method provides a way to convert the data into a unique integer, which is then used to distribute the objects evenly across hash buckets, ensuring quick access and retrieval.

When evaluating how Java calculates the hashCode() for a String, one often wonders why the multiplier 31 is used in its computation algorithm. In this article, we will delve into this oft-discussed design decision, its technical implications, and why it remains a popular choice.

Understanding the String hashCode() Implementation

The hashCode() method for Strings in Java is implemented using a polynomial accumulation technique. Here is a simplified illustration of the implementation:

java
1public int hashCode() {
2    int hash = 0;
3    for (int i = 0; i < value.length; i++) {
4        hash = 31 * hash + value[i];
5    }
6    return hash;
7}

The Power of Prime: Why 31?

  1. Prime Number Properties: The number 31 is a prime number. Prime numbers help in distributing hash values evenly, reducing the chances of different strings producing the same hash code. This is because prime numbers have fewer divisors, minimizing collision probability.
  2. Binary Optimization: The number 31 can be represented as (2^5 - 1), allowing some efficient bit-level operations. Multiplication by 31 can be optimized as (x << 5) - x, which involves a bit shift and subtraction.
  3. Balance Between Multiplication and Addition: Using an odd number ensures better distribution of hash codes. An even number could have introduced patterns, especially in environments where hash codes need to stay away from being a multiple of two, which would result in poorer distribution.
  4. Historical Context and Empirical Testing: Historically, 31 has been empirically tested and chosen as a balance between performance and collision resistance. While other multipliers have been tested, 31 consistently provided an efficient and reliable balance.

Example of Hash Code Calculation

Consider two strings: "abcd" and "bcda". Let's see how their hash codes are calculated:

For "abcd":

  • Initial hash = 0
  • hash = 31 * 0 + 'a' (97) = 97
  • hash = 31 * 97 + 'b' (98) = 3105
  • hash = 31 * 3105 + 'c' (99) = 96354
  • hash = 31 * 96354 + 'd' (100) = 2987074

For "bcda":

  • Initial hash = 0
  • hash = 31 * 0 + 'b' (98) = 98
  • hash = 31 * 98 + 'c' (99) = 3137
  • hash = 31 * 3137 + 'd' (100) = 97347
  • hash = 31 * 97347 + 'a' (97) = 3017884

The strings "abcd" and "bcda" produce different hash codes, illustrating effective distribution.

Key Points

Let's summarize the key reasons for using 31 as the multiplier in a table:

ReasonExplanation
Prime NumberReduces collision probability by distributing uniformly.
Binary OptimizationEfficient computation using (x << 5) - x.
Odd NumberPrevents even number patterns and ensures even distribution.
Historical PrecedenceSuccessfully tested and used over time.

Additional Considerations

Alternatives to 31

While 31 is the traditional choice used by Java, other constants such as 17, 37, 41, and even 1013 have been used in other libraries and languages. The key is empirical testing and understanding trade-offs between speed and collision risk.

Java Language Specification

The Java Language Specification does allow custom implementations of hashCode() methods. However, the onus is on the developer to ensure that the choice of hash function maintains a good balance between speed and collision distribution in the used context.

Conclusion

The choice of using 31 as a multiplier in Java's String hashCode() method showcases a carefully considered design decision balancing numerical properties, computational efficiency, and historical efficacy. While alternate multipliers exist, the consistent utility and performance of 31 over time have contributed to its staple status in Java’s standard library. Whether designing your own hash utils or understanding existing libraries, appreciating these nuances is valuable for any Java developer.


Course illustration
Course illustration

All Rights Reserved.