java - 如何操作不可变对象(immutable对象)树?

标签 java class-design immutability

我正在使用不可变对象(immutable对象)构建整个应用程序,以便更容易实现多线程和撤消。我正在使用 Google Collections Library它提供了不可变版本的 Map、List 和 Set。

我的应用程序模型看起来像一棵树:

  • 场景是包​​含对根节点的引用的顶级对象。
  • 每个节点都可以包含子节点和端口。

对象图可能如下所示:

Scene
 |
 +-- Node
      |
      +-- Node 
           |
           +- Port
      +-- Node
           |
           +- Port
           +- Port

如果所有这些对象都是不可变的,由顶级 SceneController 对象控制:

  • 构建此层次结构的最佳方式是什么?
  • 如何替换对象树中任意深度的对象?
  • 有没有办法支持反向链接,例如具有“父”属性的节点?

更一般地说:

  • 是否出现了处理此类数据的模式?
  • 是否有关于该主题的(学术)文献?
  • 这是个好主意吗?

最佳答案

这里有两个有趣的概念。首先,持久数据结构。如果树的所有元素都是不可变的,那么可以通过替换一些部分从原始树派生出一棵新树,但引用较旧的部分,从而节省时间和内存。

例如,如果您要向已有两个端口的节点添加第三个端口,则必须创建一个新场景、一个新场景的节点后代以及您正在更改的节点。不需要重新创建另一个节点和所有端口——您只需在新场景/节点中引用它们即可。

另一个概念是 zipper 。 zipper 是一种通过持久数据结构“导航”以优化本地更改的方法。例如,如果您添加了四个新端口而不是一个,但您一次添加每个端口一个,则您必须创建四个新场景和八个新节点。使用 zipper ,您可以推迟此类创建直到完成,从而节省这些中间对象。

我读过的关于 zipper 的最好解释是 here .

现在,使用 zipper 来导航数据结构不再需要反向链接。通过巧妙地使用递归构造函数,您可以在不可变结构中拥有反向链接。但是,这样的数据结构不会持久。非持久不可变数据结构的修改性能很差,因为每次都需要复制整个数据。

至于学术文献,我推荐 Purely Function Data Structures,作者 Okasaki(dissertation PDFfully fledged book)。

关于java - 如何操作不可变对象(immutable对象)树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2586875/

相关文章:

java - 如何创建 'get' 方法来返回 JButton

java - 表示二维数组的唯一 'code'

java - BigDecimal 和 BigInteger 的限制是什么?

java - new File() 构造函数可以在 Android 上返回 null 吗?

iphone - HTTP连接的 'didReceiveData'方法的讨论

asp.net - 隐含某种实现的接口(interface)有什么好处?

arrays - 在 flutter 中更新卡住类中的深度嵌套数组

objective-c - 如何在特殊类中建立HTTP连接?

java - 字符串如何不可变?

c# - 在 C# 中实现本地运行时不变性