- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
序列化和反序列化已成为深度复制具有复杂图形(How do you make a deep copy of an object in Java? 等)的对象的首选和接受方法,其中复制构造函数/工厂方法方法不太适合。
但是,这种方法不适用于指定初始容量的 map 。我之前关于此的问题 ( Why does specifying Map's initial capacity cause subsequent serializations to give different results? ) 显示生成的对象不相等,答案显示它们的字节表示不同:如果序列化给出 byte[] b1
,则反序列化并再次序列化将给出与 b1
不同的 byte[] b2
(至少有 1 个元素不同)。这与反序列化对象的通常行为形成对比。
控制反序列化过程的readObject
和writeObject
方法是private
,因此不能被覆盖——这可能是故意的(Hashmap slower after deserialization - Why?)。
我正在对包含许多其他对象(包括 map )的对象使用反序列化深度复制方法。我还在对它们的字节数组表示形式进行比较和更改。只要 map 未使用初始容量参数进行初始化,一切都会正常进行。但是,如上所述,尝试通过指定初始容量来优化 map 会破坏这种方法。
我想知道是否可以规避这个问题,如果可以的话如何规避。
最佳答案
好的,所以,首先,您关注的是指定初始容量会导致不同的序列化字节这一事实,这是在找错树。事实上,如果你看一下区别:
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 thresholdxp?@...: 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 thresholdxp?@...: 00 00 00 77 08 00 00 00 01 00 00 00 00 78 78 ...w.........xx
The only difference is the couple of bytes that specify load factor and such. Obviously, these bytes would be different - of course they would if you specify a different initial capacity that was ignored by the first deserialization. This is a red herring.
You are concerned about a corrupt deep copy, but this concern is misplaced. The only thing that matters, in terms of correctness, is the result of the deserialization. It just needs to be a correct, fully functional deep copy that doesn't violate any of your program's invariants. Focusing on the precise serialized bytes is a distraction: You don't care about them, in fact you only care that the result is correct.
Which brings us to the next point:
The only real issue you face here is a difference in long term performance (both speed and memory) characteristics from the fact that some Java versions ignore the initial map capacity when deserializing. This does not affect your data (that is, it will not break invariants), it only potentially affects performance.
So your very first step is to ensure that this is actually a problem. That is, it boils down to a potential premature optimization issue: Ignore the difference in the deserialized map's initial capacity for now. If your application runs with sufficient performance characteristics then you have nothing else to worry about. If it doesn't, and if you are able to narrow the bottlenecks down to decreased deserialized hash map performance due to a different initial capacity, only then should you approach this problem.
And so, the final part of this answer is, if you determine that the performance characteristics of the deserialized map actually are insufficient, there are a number of things you can do.
The simplest, most obvious one I can think of is to implement readResolve()
on your object, and take that opportunity to:
Example (from your original code example, choosing the map that yielded the "false" result):
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;
}
}
但首先要问这是否真的给您带来了问题。我相信您想多了,过度关注字节对字节的序列化数据比较对您来说没有任何成效。
关于java - 如何深度复制具有初始容量的 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39193494/
我正在使用python 2.7 当我尝试在其上运行epsilon操作时出现此错误, 这是我的代码 import cv2 import numpy as np img = cv2.imread('img
1 很多程序员对互联网行业中广泛讨论的“35岁危机”表示不满,似乎所有的程序员都有着35岁的职业保质期。然而,随着AI技术的兴起,这场翻天覆地的技术革命正以更加残酷且直接的方式渗透到各行各业。程序员
我有一个包含多个子模块的项目,我想列出每个子模块的相对深度 该项目: main_project submodule1 submodule1\submodule1_1 submo
我有一张彩色图像及其深度图,它们都是由 Kinect 捕获的。我想将它投影到另一个位置(以查看它在另一个视角下的样子)。由于我没有 Kinect 的内在参数(相机参数);我该如何实现? P.S:我正在
给出了这三个网址: 1) https://example.com 2) https://example.com/app 3) https://example.com/app?param=hello 假
这个着色器(最后的代码)使用 raymarching 来渲染程序几何: 但是,在图像(上图)中,背景中的立方体应该部分遮挡粉红色实体;不是因为这个: struct fragmentOutput {
我希望能够在 ThreeJS 中创建一个房间。这是我到目前为止所拥有的: http://jsfiddle.net/7oyq4yqz/ var camera, scene, renderer, geom
我正在尝试通过编写小程序来学习 Haskell...所以我目前正在为简单表达式编写一个词法分析器/解析器。 (是的,我可以使用 Alex/Happy...但我想先学习核心语言)。 我的解析器本质上是一
我想使用像 [parse_ini_file][1] 这样的东西。 例如,我有一个 boot.ini 文件,我将加载该文件以进行进一步的处理: ;database connection sett
我正在使用 Mockito 来测试我的类(class)。我正在尝试使用深度 stub ,因为我没有办法在 Mockito 中的另一个模拟对象中注入(inject) Mock。 class MyServ
我试图在调整设备屏幕大小时重新排列布局,所以我这样做: if(screenOrientation == SCREEN_ORIENTATION_LANDSCAPE) { document
我正在 Ubuntu 上编写一个简单的 OpenGL 程序,它使用顶点数组绘制两个正方形(一个在另一个前面)。由于某种原因,GL_DEPTH_TEST 似乎不起作用。后面的物体出现在前面的物体前面
static FAST_FUNC int fileAction(const char *pathname, struct stat *sb UNUSED_PARAM, void *mo
我有这样的层次结构: namespace MyService{ class IBase { public: virtual ~IBase(){} protected: IPointer
我正在制作一个图片库,需要一些循环类别方面的帮助。下一个深度是图库配置文件中的已知设置,因此这不是关于无限深度循环的问题,而是循环已知深度并输出所有结果的最有效方法。 本质上,我想创建一个 包含系统中
如何以编程方式在树状结构上获取 n 深度迭代器?在根目录中我有 List 每个节点有 Map> n+1 深度。 我已修复 1 个深度: // DEPTH 1 nodeData.forEach(base
我正在构建一个包含大量自定义元素的 Polymer 单页界面。 现在我希望我的元素具有某种主样式,我可以在 index.html 或我的主要内容元素中定义它。可以这样想: index.html
我正在尝试每 25 秒连接到配对的蓝牙设备,通过 AlarmManager 安排,它会触发 WakefulBroadcastReceiver 以启动服务以进行连接。设备进入休眠状态后,前几个小时一切正
假设有一个有默认值的函数: int foo(int x=42); 如果这被其他人这样调用: int bar(int x=42) { return foo(x); } int moo(int x=42)
是否可以使用 Javascript 获取 url 深度(级别)? 如果我有这个网址:www.website.com/site/product/category/item -> depth=4www.w
我是一名优秀的程序员,十分优秀!