在Java中缓存和重用不可变单例对象的最佳方法是什么?

我有一个表示一组值的类,这些值将用作映射中的键。

这个类是不可变的,我想使用静态工厂模式使它成为每个不同值集的单例。 目标是防止相同对象被创建多次(100+)次并优化equals方法。

我正在寻找缓存和重用此类的先前实例的最佳方法。 首先想到的是一个简单的hashmap,但还有其他选择吗?

有两种情况:

  • 如果不同对象的数量很小并且已修复,则应使用enum
    • 除了声明的常量之外,它们不是可实例化的,并且EnumMap针对它进行了优化
  • 否则,您可以按计划缓存不可变实例:
    • 如果值可以通过连续范围内的数字进行索引,则可以使用数组
      • 这是例如valueOf的给定范围内的Integer缓存实例
    • 否则你可以使用某种Map

根据使用模式,您可以选择仅缓存最后N个实例,而不是目前为止创建的所有实例。 这是在Python的正则表达式模块中用于例如re.compile的方法。 如果N足够小(例如5),则具有线性搜索的简单数组也可以正常工作。

对于基于Map的解决方案,也许一个有用的实现是java.util.LinkedHashMap ,它允许您在@Override removeEldestEntry强制执行类似LRU的策略。

Apache Commons Collections还提供LRUMap ,可以更直接地实施此策略。

也可以看看

  • Java教程/ enums
  • 有效的Java第2版,第1项:考虑静态工厂方法而不是构造函数
  • 维基百科/ Flyweight模式

相关问题

  • 在java中使用简单易用的LRU缓存
  • LRU LinkedHashMap根据可用内存限制大小
    • 番石榴MapMaker ,软键和值等
  • 如何在Java 6中实现LRU缓存?

您尝试制作的内容听起来像是Flyweight模式的一个示例,因此寻找对此的引用可能有助于澄清您的想法。

将它们存储在某种地图中确实是一种常见的实现方式。

你的对象是什么样的? 如果您的对象相当简单,我认为您应该考虑不缓存它们 – 对象创建通常非常快。 我认为您应该评估可能的小性能提升是否值得增加缓存的复杂性和工作量。