Java 重用缓存实例
我有一个应用程序使用数据结构Java 重用缓存实例,java,caching,Java,Caching,我有一个应用程序使用数据结构点。假设总共有50个不同的点实例(意思是p1.equals(p2)==false)。但是,在计算过程中会创建新实例的负载,这些新实例实际上与已实例化的对象相同 由于存储了这些实例,这对内存消耗有很大影响: 50个不同的点由50万个点实例表示。在数据结构中,没有任何东西会阻止重用已经存在的实例。因此,我创建了一个缓存: HashMap<Point, Point> pointCache = new HashMap<>(); HashMap poi
点
。假设总共有50个不同的点实例(意思是p1.equals(p2)
==false)。但是,在计算过程中会创建新实例的负载,这些新实例实际上与已实例化的对象相同
由于存储了这些实例,这对内存消耗有很大影响:
50个不同的点
由50万个点
实例表示。在数据结构中,没有任何东西会阻止重用已经存在的实例。因此,我创建了一个缓存:
HashMap<Point, Point> pointCache = new HashMap<>();
HashMap pointCache=newhashmap();
因此,我可以检查该点是否存在,如果不存在,则添加该点。然而,这种缓存看起来有点过分,因为键和值本质上是相同的
此外,我已经有了一张地图:
HashMap<Point, Boolean> flag = new HashMap<>();
HashMap flag=newhashmap();
我好奇的是:是否有一个类似于地图的数据结构,我可以用于标志
,允许检索密钥?如果没有的话,是否还有其他数据结构可以用于缓存,它更像一个集合,并且可以方便地进行检查和检索
编辑:为了完整起见,我使用的点
类是javafx.geometry.Point2D
,因此我无法更改任何内容。您的地图是完全合理的。如果愿意的话,您可以创建自己的包装器类,但我现在可能会坚持使用map。如果Set
公开了“获取与此项相等的现有项”的操作,则可以使用该操作,但是a)没有,b)HashSet
无论如何都是建立在HashMap
上的。最好使用HashSet
而不是HashMap
,这样可以避免对每个点存储不同的布尔值。虽然Set
会在内部使用HashMap
,但它会使用相同的对象
引用,这比存储奇数的50个布尔值要好,因为这些值在您的情况下没有意义,也没有用处
您可以执行如下查找:
if (set.contains(point)) {
...
}
为了得到这个答案,我们假设点
的唯一性由两个int坐标x和y确定(您可以轻松更改该坐标,以适合确定点
唯一性的实际参数)
您不想创建一个点
实例来确定该点
是否已经存在于某些哈希集
或哈希映射
中。这违背了避免创建多个实例的目的(尽管使用HashMap
或HashSet
会阻止您保留所有这些重复实例,并且GC将很快释放它们,因此可能足以解决内存消耗问题)
我建议在Point
类中使用静态Point-getPoint(intx,inty)
方法。该方法将在静态内部HashMap
中检查这些x、y坐标是否已经有相应的点
实例,并返回该实例。如果一个实例不存在,它将被创建并添加到HashMap
这类似于Integer.valueOf(int)
对小整数所做的操作-它返回一个缓存的Integer
实例,而不是创建一个新实例。通常这似乎是一个好的解决方案,不幸的是,我的Point
类是javafx.geometry.Point2D
,因此我无法更改它。提供我自己的点
类是否值得花费开销?@hotzst您仍然可以使用点2d
类,而无需包装它。只需创建一个Point2DFactory
类,该类将维护缓存,并用于获取那些Point2D
实例。Integer
s只缓存较小的值(如果我没记错的话,为0-127)。和Double
s(Point2D
所需的)根本不会被缓存。因此,除非坐标始终是0-127范围内的整数,否则您仍然会为每个哈希映射查找创建两个(短期)对象。使用Point2D
对象作为键看起来更清晰(或者简单地使用哈希集
)似乎更清楚。@IntegerCache只是缓存少量实例的一个示例。OP需要50个不同的点实例,因此本例中的缓存比IntegerCache小。请参阅Guava的和。看起来很有希望,谢谢@BenManes