PDFBox中SmallMap未遵循Map.Entry哈希码规范问题咨询
PDFBox中SmallMapEntry哈希码实现不符合Map.Entry规范的问题
我在基于PDFBox做PDF文档资源合并的优化工作时,花了数小时排查哈希碰撞过多的原因,最终发现最新版PDFBox存在一个潜在问题:COSDictionary的entrySet由SmallMap提供支持,其内部类SmallMapEntry的hashCode()方法仅返回key的哈希值,但Map.Entry的官方规范明确要求哈希码是key与value哈希值的异或结果。
我的代码片段
if (object instanceof COSDictionary) { int result = 3; for (Map.Entry<COSName, COSBase> entry : ((COSDictionary) object).entrySet()) result += entry.hashCode(); if (object instanceof COSStream) { // ... 其他逻辑 } }
PDFBox中SmallMapEntry的hashCode实现
public int hashCode() { return this.getKey().hashCode(); }
Map.Entry的官方规范(JavaDoc)
/**
- 返回此映射项的哈希码值。映射项 {@code e} 的哈希码定义为:
(e.getKey()==null ? 0 : e.getKey().hashCode()) ^(e.getValue()==null ? 0 : e.getValue().hashCode())- 这确保对于任意两个项 {@code e1} 和 {@code e2},{@code e1.equals(e2)} 意味着
- {@code e1.hashCode()==e2.hashCode()},这符合 {@code Object.hashCode} 的通用约定。
- @return 此映射项的哈希码值
- @see Object#hashCode()
- @see Object#equals(Object)
- @see #equals(Object)
*/
int hashCode();
结论
这毫无疑问是一个bug。它直接违反了Map.Entry接口的规范约定,还会导致相同key但不同value的Entry拥有相同的哈希码——这不仅会大幅增加哈希碰撞概率(就像我遇到的情况),还会破坏所有依赖Map.Entry哈希正确性的场景,比如将这些Entry存入HashSet时,会出现逻辑错误(误判不同Entry为相等)。
内容的提问来源于stack exchange,提问作者Guyard
相关产品推荐
相关产品推荐

