2

我从 2008 年开始在一台机器上开发,不幸的是目前无法升级。我真的需要优化我正在构建的这个工具的性能。

我的整个项目相当大,我目前正在创建自己的地图编辑器,以便以后为我的主要项目创建地图。它相当简单,旨在加载、保存和编辑地图拥有的“瓷砖”数组。它基本上是一个 2D 地图编辑器,根据我的需要进行定制。

编辑器预览


当地图加载到编辑器中时,它的 Tileset(一个大的 BufferedImage)被分解为每个单独的 Tile(具有较小的 BufferedImage),加载到 GUI 的右侧成为一大堆带有图标的 JLabel。我使用了各种 Swing LayoutManager 来实现我想要的定位。

在 MapCanvas 区域内,基本上做了同样的事情。每个 Tile,无论是否为空,都有一个带有图标的 JLabel,加载到 Grid 上。我之前曾询问过使用 Swing 组件是否比使用 Java2D 来设计和绘图更有效,并且一致认为这并不重要(老实说,Swing 可能比我写的更好我)。


我相信我的问题源于我互连每个 JLabel 及其图标的方式。

我的目标是减少我必须创建的重复图标的数量,这在理论上应该减少内存使用和 CPU 使用。编辑器中的磁贴交互如下:

  • 如果没有选择要“标记”的图块,则只会在 JLabel 的图标上绘制一个颜色的 alpha 合成,以表示它正在悬停,并且将在 MouseExit 时恢复
  • 如果活动的图章工具上有一个图块,该图块的图像将临时替换 JLabel 的图标以表示它正在悬停,并且将在 MouseExit 时恢复
  • 如果活动图章工具上有一个图块,并且单击了一个 JLabel,则该 JLabel 的图标将“永久”设置为活动图章图块,除非还原
  • 如果启用 Grid Lines 选项,每个 JLabel 的图标将通过 ImageFactory 处理,以使虚线沿着顶部和左侧边缘延伸(形成网格,如图所示)如果缩放级别发生变化,每个JLabel 的preferredSize 设置为可容纳,并且必须在ImageFactory 中调整图标的大小(根据应用的网格线)


将 Map 加载到编辑器后,会创建每个 JLabel,并给出其对应的 BufferedImage(无论是否为空),然后将其放入 Map 的字段 ArrayList 中。设置了 preferredSize 以使 Layout 看起来正确,并将其添加到 MapCanvas(它只是一个 JPanel)。

我创建了各种 ArrayList 和 HashMap 对象,以便可以将 JLabel 作为 Key 传递,并返回 BufferedImage。这样,当悬停在 JLabel 上时,MouseEvent 可以将事件的源发送回侦听器,并且它可以根据接收到的 JLabel 获取正确的 BufferedImage。然后图像可以由我的 ImageFactory 类以上面列出的方式之一处理。

所以基本上当 JLabel 收到 MouseEvent 时,会发生这种情况:

  • MouseEvent 将源 JLabel 发送到 ActionListener
  • Listener 使用源 JLabel 作为 Key 来获取所需的 BufferedImage 块
  • 然后相应地处理 BufferedImage 块(可以是颜色 Alpha 合成、应用到它的缩放因子或添加到它的网格线,或这些的组合)

没有更好的方法来做到这一点?这对我用了 2 年的笔记本电脑没有任何明显的影响,但是当鼠标与我的旧台式机上的 JLabels 交互时,会有非常明显的延迟。

鉴于我将在两者上积极开发,我希望环境能够顺利运行,如果这意味着我必须对内存和 CPU 使用更严格,那就这样吧。

但我似乎真的想不出一个内存效率更高的系统。

ArrayLists 和 HashMaps 是问题吗?许多图像操作是问题吗?

我已经以各种方式利用了 JLabel 的“setName(String)”方法(例如,每个 JLabel 都有一个名称,其中包含它在 JLabel 的一维数组中的位置,以及它在图表上的 x 和 y 坐标,即“maptile#24:1,9”),但这需要遍历数组,我希望专门用键抓取 BufferedImages 会更有效。

4

1 回答 1

0

Java 集合是动态的,这意味着它们会随着您添加数据而调整大小。它们大小调整函数的实际模型(由 ArrayList 和可能是 HashMap 使用)类似于当它们达到容量时它们的容量加倍,这包括在内存中声明一个新块并复制所有存储的数据。

如果您知道每个HashMaps 和ArrayLists 的最大可能大小,您可能会从使用具有初始容量的构造函数中受益。Here & Here这将防止他们使用不必要的内存。并将防止任何可能的延迟增加容量。

您还可以从阅读每种类型的文档的前几段中受益,因为它们可以很好地解释有效使用(例如HashMap,s loadfactor)。

考虑其他类型的 List 和 Map 也可能对您有用(如果您不知道它们的实现中的差异),例如,LinkedList删除和插入操作比 更有效ArrayList,但是随机访问要慢得多index 比 anArrayList必须遍历每个先前的索引才能到达所需的索引,而 anArrayList可以直接访问所需的索引。

但是,很难猜测您根据这些建议所做的任何更改会有多明显。

于 2013-08-14T09:28:15.690 回答