我实现了一个简单的序列化机制。序列化对象以递归方式遍历其字段并将其写入流中。为了避免无限循环,当遇到要写入的对象时,检查它是否在之前看过它,如果是,那么它会写入一个标记。这依赖于维护它之前看到的可搜索的对象列表。列表的indexOf()
和contains()
方法无法使用Object.equals
,因此必须使用==
,因为对象图中可能包含两个对象在数据方面是相同的,但实际上不应该是同一个对象。如果我使用带有以下示例图的简单Map<Object, Integer>
,那么会发生一些不好的事情:
root: ParentObject (class Parent)
field1: ChildObject1 (class Child)
data: "Hello"
field2: ChildObject2 (class Child)
data: "Hello"
序列化后,当Map
被要求查看之前是否已写入ChildObject1
时ChildObject2
找到.equals()
,因为 root: ParentObject (class Parent)
field1: ChildObject1 (class Child)
data: "Hello"
field2: <reference to ChildObject1>
方法返回true。反序列化时,对象树现在看起来像这样:
ChildObject1
现在的问题是,如果某些内容修改了ChildObject2
,那么明显的List<Object>
也会发生这种变化,这与序列化之前发生的行为不同。如果这些对象是不可变的,那么这不会成为问题,但是这种机制是通用的,并且不能确保不变性,并且在特定情况下我实际上需要对象也不是不可变的。
在较低级别的语言中,我只是根据指针地址创建一个查找,但这不是一个选项。
我可以使用简单的list.get(i) == needle
,并对Unsafe
进行线性搜索,但效率非常低。我的第一个想法是简单的二进制搜索,但我搜索什么?没有识别信息,没有密钥可供使用。这似乎排除了使用任何更有效的查找结构。
我过去曾使用$(function(){
var color, height, width;
function makeGrid(){
var table = $('pixel_canvas');
height = $("#input_height").val();
width = $("#input_width").val();
color = $("#colorPicker").val();
console.log(color);
console.log(width);
console.log(height);
for (var i = 0; i<height; i++){
row = table.insertRow(i);
for(var j = 0; j<width; j++){
pixel = row.insertCell(j);
$(pixel).css({
'border': 'black solid 1px'
});
console.log(pixel);
$(pixel).on("click", function(){
$(this).css({'background-color':'color'});
})
}
}
}
$("#sizePicker").on('submit', function(){
makeGrid();
});
});
来输出身份信息(基本上是对象的指针),以便进行调试日志记录,但这似乎是,#34;不安全&#34;!在我的脑海里,我有这样的想法,即JVM可以自由地移动,例如在GC之后,这也会破坏这种方法。
我如何解决这个问题?
答案 0 :(得分:2)
列表的线性扫描将为O(N)
,其中N
是列表长度。这样效率不高,你无法提高效率。
您可以使用System.identityHashcode(Object)
来计算与==
兼容的哈希码。
但是有一个更简单的解决方案。有一个名为Map
的{{1}}类,它非常适合您的用例。此IdentityHashMap
实施具有Map
查找和插入(已摊销)