最初に、最初の容量を指定するとシリアル化された別のバイトにつながるという事実に焦点を当て、間違ったツリーを作り上げています。実際には、違いを見ると、
pbA from your example:
: ac ed 00 05 73 72 00 0f 71 33 39 31 39 33 34 39 ....sr..q3919349
: 34 2e 53 74 61 74 65 00 00 00 00 00 00 00 01 02 4.State.........
: 00 01 4c 00 04 6d 61 70 73 74 00 10 4c 6a 61 76 ..L..mapst..Ljav
: 61 2f 75 74 69 6c 2f 4c 69 73 74 3b 78 70 73 72 a/util/List;xpsr
: 00 13 6a 61 76 61 2e 75 74 69 6c 2e 41 72 72 61 ..java.util.Arra
: 79 4c 69 73 74 78 81 d2 1d 99 c7 61 9d 03 00 01 yListx.....a....
: 49 00 04 73 69 7a 65 78 70 00 00 00 01 77 04 00 I..sizexp....w..
: 00 00 01 73 72 00 14 71 33 39 31 39 33 34 39 34 ...sr..q39193494
: 2e 4d 61 70 57 72 61 70 70 65 72 00 00 00 00 00 .MapWrapper.....
: 00 00 01 02 00 01 4c 00 03 6d 61 70 74 00 0f 4c ......L..mapt..L
: 6a 61 76 61 2f 75 74 69 6c 2f 4d 61 70 3b 78 70 java/util/Map;xp
: 73 72 00 11 6a 61 76 61 2e 75 74 69 6c 2e 48 61 sr..java.util.Ha
: 73 68 4d 61 70 05 07 da c1 c3 16 60 d1 03 00 02 shMap......`....
: 46 00 0a 6c 6f 61 64 46 61 63 74 6f 72 49 00 09 F..loadFactorI..
: 74 68 72 65 73 68 6f 6c 64 78 70 3f 40 00 00 00 [email protected]
: 00 00 02 77 08 00 00 00 02 00 00 00 00 78 78 ...w.........xx
zero from your example:
: ac ed 00 05 73 72 00 0f 71 33 39 31 39 33 34 39 ....sr..q3919349
: 34 2e 53 74 61 74 65 00 00 00 00 00 00 00 01 02 4.State.........
: 00 01 4c 00 04 6d 61 70 73 74 00 10 4c 6a 61 76 ..L..mapst..Ljav
: 61 2f 75 74 69 6c 2f 4c 69 73 74 3b 78 70 73 72 a/util/List;xpsr
: 00 13 6a 61 76 61 2e 75 74 69 6c 2e 41 72 72 61 ..java.util.Arra
: 79 4c 69 73 74 78 81 d2 1d 99 c7 61 9d 03 00 01 yListx.....a....
: 49 00 04 73 69 7a 65 78 70 00 00 00 01 77 04 00 I..sizexp....w..
: 00 00 01 73 72 00 14 71 33 39 31 39 33 34 39 34 ...sr..q39193494
: 2e 4d 61 70 57 72 61 70 70 65 72 00 00 00 00 00 .MapWrapper.....
: 00 00 01 02 00 01 4c 00 03 6d 61 70 74 00 0f 4c ......L..mapt..L
: 6a 61 76 61 2f 75 74 69 6c 2f 4d 61 70 3b 78 70 java/util/Map;xp
: 73 72 00 11 6a 61 76 61 2e 75 74 69 6c 2e 48 61 sr..java.util.Ha
: 73 68 4d 61 70 05 07 da c1 c3 16 60 d1 03 00 02 shMap......`....
: 46 00 0a 6c 6f 61 64 46 61 63 74 6f 72 49 00 09 F..loadFactorI..
: 74 68 72 65 73 68 6f 6c 64 78 70 3f 40 00 00 00 [email protected]
: 00 00 00 77 08 00 00 00 01 00 00 00 00 78 78 ...w.........xx
唯一の違いはthe couple of bytes that specify load factor and suchです。明らかに、これらのバイトはコースのものとは異なります。最初のデシリアライゼーションで無視された別の初期容量を指定するとします。 これは赤いニシンです。
壊れたディープコピーが心配ですが、この懸念は間違っています。 正しさの点で重要なのは、逆シリアル化の結果だけです。これは、プログラムのインバリアントに違反しない、完全で機能的な正しいディープコピーである必要があります。正確なシリアライズされたバイトに焦点を当てることは注意散漫です。あなたはそれらについて気にしません。実際は、結果が正しいことだけを気にします。次のポイントに私たちをもたらします
:あなたがここに直面
のみ本当の問題は、長期性能に差(速度とメモリの両方)いくつかのJavaのバージョンは、初期マップを無視しているという事実から特性でありますデシリアライズ時の容量これはデータには影響しません(つまり、不変量は破られません)。
だからあなた非常に最初のステップが、これは実際に問題であることを確認にあります。つまり、早急な最適化問題が発生する可能性があります。現在、非直列化マップの初期容量の違いを無視します。あなたのアプリケーションが十分な性能特性で動作するなら、あなたは心配する必要がありません。そうでない場合、および異なる初期容量のために、逆シリアル化されたハッシュマップのパフォーマンスが低下するようにボトルネックを絞り込める場合は、との方がよいでしょうか。
したがって、の場合、逆シリアル化マップのパフォーマンス特性が実際には不十分であると判断した場合、実行できることがいくつかあります。適切なパラメータを使用して新しいマップ(初期容量など)を構築し
:
私は考えることができる最も簡単な、最も明白な一つは、あなたのオブジェクトにreadResolve()
を実装、およびにその機会を利用しています
- 古い非直列化マップのすべてのアイテムを新しいマップにコピーします。
- 古いマップを破棄し、新しい地図と置き換えます。
例(元のコード例から、「偽」の結果をもたらしたマップを選択する):
class MapWrapper implements Serializable {
private static final long serialVersionUID = 1L;
Map<String, Integer> map = new HashMap<>(2);
private Object readResolve() throws ObjectStreamException {
// Replace deserialized 'map' with one that has the desired
// capacity parameters.
Map<String, Integer> fixedMap = new HashMap<>(2);
fixedMap.putAll(map);
map = fixedMap;
return this;
}
}
しかし、最初の質問、これは本当にあなたのための問題を引き起こしている場合。私はあなたがそれを思い知らされていると信じており、byte-for-byteシリアル化されたデータの比較に焦点を当てることはあなたにとって生産的ではありません。
「アプローチを破る」のはなぜですか?容量が異なることについて「壊れている」とは何ですか? 'HashMap'の反復順序は、*具体的には*任意であると定義されているので、反復順序は言いません。 – Andreas
私はAndreasと同じ質問があります。このアプローチでどのような問題が発生しているのかを明確にすることはできますか?そして、実際には、小さな代表例*が本当にここで助けます。 –
また、簡単な提案と同じように、あなたはチャンスを持っています。 ['readResolve() '](https://docs.oracle.com/javase/7/docs/platform/serialization/spec/input.html#5903)のデシリアライズ後にマップなどを再構築してください。したがって、あなたが本当に壊れていると仮定し、それが別の問題ではなく、別のアプローチを完全に排除すると、 'readResolve()'に適切なパラメータを使ってマップを再構築する可能性があります。 –