Fundamentals 10 min read

Understanding Java Float hashCode: Why -0.0 and 0.0 Behave Differently as Map Keys

This article explains how Java's Float hashCode treats 0.0 and -0.0 as distinct values, causing unexpected behavior when using floating‑point numbers as HashMap keys, and shows how to debug, reproduce, and avoid the issue by using alternative representations.

Top Architect
Top Architect
Top Architect
Understanding Java Float hashCode: Why -0.0 and 0.0 Behave Differently as Map Keys

The author, a senior architect, was solving the classic interview problem "max points on a line" and discovered that using a floating‑point slope as a HashMap key produced wrong results because the values 0.0 and -0.0 were treated as different.

Initial solution (simplified):

import java.util.HashMap;
import java.util.Map;
public class Solution {
    public int maxPoints(Point[] points) {
        if (points.length <= 2) return points.length;
        int max = 2;
        for (int i = 0; i < points.length - 1; i++) {
            Map
map = new HashMap<>(16);
            int ver = 0, dup = 0, cur;
            for (int j = i + 1; j < points.length; j++) {
                if (points[j].x == points[i].x) {
                    if (points[j].y != points[i].y) ver++; else dup++;
                } else {
                    float d = (float) ((points[j].y - points[i].y) / (double) (points[j].x - points[i].x));
                    map.put(d, map.get(d) == null ? 1 : map.get(d) + 1);
                }
            }
            cur = ver;
            for (int v : map.values()) cur = Math.max(v, cur);
            max = Math.max(max, cur + dup + 1);
        }
        return max;
    }
}

Debugging showed that the two slopes (3‑3)/(3‑2) and (3‑3)/(-5‑2) produced 0.0 and -0.0 respectively, and the map considered them different keys, leading to an output of 2 instead of the expected 3.

Test code confirming the discrepancy:

System.out.println(0.0 == -0.0); // true
System.out.println(new Float(0.0).hashCode() == new Float(-0.0).hashCode()); // false

Investigation of Float.equals and Float.hashCode revealed that equality uses floatToIntBits , which distinguishes -0.0 (bit pattern 0x80000000) from +0.0 (bit pattern 0x00000000). Consequently, their hash codes differ even though the numeric values compare equal.

Key excerpts from the JDK source:

public boolean equals(Object obj) {
    return (obj instanceof Float) &&
           (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}

public static int floatToIntBits(float value) {
    int result = floatToRawIntBits(value);
    if ((result & FloatConsts.EXP_BIT_MASK) == FloatConsts.EXP_BIT_MASK &&
        (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
        result = 0x7fc00000; // canonical NaN
    return result;
}

Running the following prints confirms the bit patterns:

System.out.println(Float.floatToIntBits(0.0f));          // 0
System.out.println(Float.floatToIntBits(-0.0f));         // -2147483648 (0x80000000)

Because of these subtleties—different hash codes for values that compare equal, special handling of NaN, infinities, and signed zero—floating‑point numbers are unsafe as HashMap keys. A more reliable approach for the line‑finding problem is to represent a line with integer coefficients (Ax + By + C = 0) or use BigDecimal for precise slope calculations.

In summary, Java’s Float implementation follows the IEEE‑754 standard, which makes -0.0 a distinct bit pattern; this leads to different hash codes and unexpected map behavior, so developers should avoid using raw floating‑point values as map keys.

JavaprogrammingHashMapieee754floatHashCodenegative-zero
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.