我正在使用Java开发一些金融算法。我有一个复杂的数据结构,其中包含许多需要在算法生命周期内更新的属性。有时这个数据结构会更新1000多次......
为了提高性能,特别是对于get(search)/update/insert
,我决定使用 TreeMap
作为容器,这在这方面非常有效。
现在是具有挑战性的部分。我需要更新数据结构属性,我需要从容器中检索它,这需要:
- 检查容器是否具有对象
- 如果是,则获取对象,否则创建新对象并添加到地图
- 更新对象(如果容器中存在)
这个过程需要三个 x log(n),即检查、获取和放置。我想在单个日志(n)时间内执行此操作。
为此,我的解决方案是:
我总是使用put
在地图(insert/update/get
)中添加对象。 put
返回旧对象,我用旧值更新当前对象,这解决了 log(n),但不同的对象失去了对前一个对象的引用,因为新值在映射中被替换。
是否有更好的解决方案或更好的容器来更新数据结构。我可以使用List
并使用集合的二叉搜索,但为此我需要再次对数据结构进行排序,因为列表未排序。
请指导
我认为你做得很好。
O(k.log(n)) = O(log(n))
其中 k 是一个常数。所以你的时间复杂度实际上是O(log(n))
如果你切换到ConcurrentMap.computeIfAbsent(...),你可以一口气实现1
和2
。它返回新/旧对象,以便您可以更新它。
如果是Java-7,那么放IfAbsent,但这需要额外的new
- 如果建筑昂贵,这可能是一件坏事。
如果您不害怕周围有可变对象(您似乎已经给出了您提出的解决方案),您可以通过 1-2 个操作来完成。而不是
1. contains()
2a. exists? get(), modify, put()
2b. doesn't exist? create, put()
你可以做
1. get()
2a. null? create put()
2b. not-null? modify object contents, as you already have reference
这样,现有对象就有 1 个搜索操作,非现有对象有 2 个搜索操作。
如果你想进一步改进它,你可能想使用ConcurrentHashMap(在你克服了对哈希码的不信任之后;)和放置如果缺席
1. old = putIfAbsent(createFresh())
2. old not null? update old
说了这么多,我通常会尝试避免使用可变对象,因为可变对象的时间长于单个方法的生命周期。在某些时候,您可能希望多线程处理,并且具有可变的东西会使它变得更加复杂。但是有各种权衡(如内存压力),所以这取决于你。但是请认真研究哈希图,它们可能是您可以在这里进行的最大优化,无论对象(不)可变性如何。