PDFBox SmallMap 不尊重 Map.Entry 哈希码合约

问题描述 投票:0回答:1

我正在研究一个优化过程,以将 pdf 文档中的资源与 PDFBox 合并。

经过数小时研究为什么我的代码会生成太多哈希冲突,我惊讶地发现最新版本的 PDFBox 中存在潜在错误。

让我解释一下:在 COSDictionary 中,entrySet 由 SmallMap 支持。 如果你想计算 COSDictionary EntrySet 对象生成的 Map.Entry 的 hashcode,你会发现 hashcode 是这样计算的。

我的代码:

if (object instanceof COSDictionary) {
                int result = 3;
                for (Map.Entry<COSName, COSBase> entry : ((COSDictionary) object).entrySet())
                    result += entry.hashCode();
                if (object instanceof COSStream) { .... ..... ....}

在类中,SmallMap 和内部类 SmallMapEntry (PDFBox) :

public int hashCode() {
            return this.getKey().hashCode();
        }

但是 Map.Entry 中的一般契约明确指出(JavaDoc):

         /**
         * Returns the hash code value for this map entry.  The hash code
         * of a map entry {@code e} is defined to be: <pre>
         *     (e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
         *     (e.getValue()==null ? 0 : e.getValue().hashCode())
         * </pre>
         * This ensures that {@code e1.equals(e2)} implies that
         * {@code e1.hashCode()==e2.hashCode()} for any two Entries
         * {@code e1} and {@code e2}, as required by the general
         * contract of {@code Object.hashCode}.
         *
         * @return the hash code value for this map entry
         * @see Object#hashCode()
         * @see Object#equals(Object)
         * @see #equals(Object)
         */

int hashCode();

我认为这是 PDFBox 中的一个错误,但我不确定,您对此有何看法?

java pdfbox
1个回答
2
投票

事实上,

SmallMapEntry
方法
hashCode
并没有按照Map.Entry的JavaDocs中的
定义
来实现。同样,
SmallMapEntry.equals
未按
Map.Entry.equals
的定义实现,
SmallMap.hashCode
未按
Map.hashCode
的定义实现,
SmallMap.equals
未按
Map.equals
的定义实现。

但是这是有原因的,而且不仅仅是懒惰或性能:

Map
JavaDocs 本身解释了其
hashCode
equals
定义的缺点:

/**
 * ...
 * <p>Some map operations which perform recursive traversal of the map may fail
 * with an exception for self-referential instances where the map directly or
 * indirectly contains itself. This includes the {@code clone()},
 * {@code equals()}, {@code hashCode()} and {@code toString()} methods.
 * ...
PDF 中的字典通常间接包含自身(例如通过

KidsParent 条目),因此如果在 JavaDocs 中实现为 definehashCode

 通常会因堆栈溢出而失败。因此,防止递归遍历的实现(例如,仅比较条目的键)实际上在这里是有利的。

© www.soinside.com 2019 - 2024. All rights reserved.