簡體   English   中英

有效搜索列表以查找特定實例,而無需使用equals()或hashCode()

[英]Efficiently searching a list to find specific Instance, without using `equals()` or `hashCode()`

我正在實現一個簡單的序列化機制。 序列化對象以遞歸方式拖曳其字段並將其寫出到流中。 為了避免無限循環,當遇到對象寫入時,它會檢查是否以前看過它,如果是,那么它會寫一個標記。 這依賴於維護以前見過的對象的可搜索列表。 列表的indexOf()contains()方法不能使用Object.equals ,而必須使用== ,因為對象圖中可能有兩個對象,它們在數據方面是相同的,但實際上不應該是同一對象。 如果我將簡單的Map<Object, Integer>與下面的示例圖一起使用,則會發生一些不良情況:

   root: ParentObject (class Parent)
      field1:  ChildObject1 (class Child)
         data: "Hello"
      field2:  ChildObject2 (class Child)
         data: "Hello"

當被序列化時,當.equals()方法返回true時, Map被問到是否ChildObject2編寫過ChildObject1時會找到ChildObject1 反序列化后,對象樹現在如下所示:

   root: ParentObject (class Parent)
      field1:  ChildObject1 (class Child)
         data: "Hello"
      field2:  <reference to ChildObject1> 

現在的問題是,如果某些東西修改了ChildObject1那么表面上的ChildObject2也會發生這種變化,這與序列化之前的行為是不同的。 如果這些對象是不可變的,那么這將不是問題,但是這種機制是通用的,不能確保不可變性,在特定情況下,對於對象也不是不可變的,我實際上需要它。

在較低級別的語言中,我將僅基於指針地址創建查找,但這不是這里的選擇。

我可以使用簡單的List<Object> ,並對list.get(i) == needle進行線性搜索,但這效率很低。 我首先想到的是一個簡單的二進制搜索,但是我該搜索什么呢? 沒有要使用的識別信息,也沒有密鑰。 這似乎排除了使用任何更有效的查找結構的可能性。

過去,我曾使用Unsafe來輸出身份信息(基本上是對象的指針)以進行調試日志記錄,但這似乎是“ unsafe”! 在我的腦海中,我想到JVM可以自由移動,例如在GC之后,這也將打破這種方法。

我該如何解決這個問題?

列表的線性掃描將是O(N) ,其中N是列表長度。 那不是有效的,您也無法使其有效。

您可以使用System.identityHashcode(Object)計算將與==兼容的哈希碼。

但是,有一個更簡單的解決方案。 有一個名為IdentityHashMapMap類,該類非常適合您的用例。 Map實現具有O(1)查找和插入(攤銷)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM