Java 多选项卡映射/平铺级编辑器中的CPU/内存效率(许多HashMaps/ArrayList)

Java 多选项卡映射/平铺级编辑器中的CPU/内存效率(许多HashMaps/ArrayList),java,arraylist,hashmap,cpu-usage,memory-efficient,Java,Arraylist,Hashmap,Cpu Usage,Memory Efficient,我从2008年开始在一台机器上开发,不幸的是目前无法升级。我真的需要优化我正在构建的这个工具的性能 我的整个项目相当大,目前我正在创建自己的地图编辑器,以便在以后为我的主要项目创建地图。它相当简单,设计用于加载、保存和编辑地图拥有的“瓷砖”数组。它基本上是一个2D地图编辑器,根据我的需要定制 当地图加载到编辑器中时,其平铺集(一个大的BuffereImage)被分解为每个单独的平铺(带有一个较小的BuffereImage),并加载到GUI的右侧,形成一大串带有图标的JLabel。我使用了各种

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

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


当地图加载到编辑器中时,其平铺集(一个大的BuffereImage)被分解为每个单独的平铺(带有一个较小的BuffereImage),并加载到GUI的右侧,形成一大串带有图标的JLabel。我使用了各种Swing布局经理来实现我想要的定位

在MapCanvas区域内,基本上完成了相同的操作。每个磁贴(无论是否为空)都有一个带有图标的JLabel,加载到网格中。我曾经询问过使用Swing组件是否比使用Java2D进行设计和绘图更有效,一致认为这并不重要(老实说,Swing可能比我自己编写的更好)


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

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

  • 如果没有选择要“冲压”的平铺,则只会在JLabel的图标上绘制一种颜色的alpha合成,表示它正在悬停,并在鼠标退出时恢复
  • 如果激活的Stamp tool上有一个互动程序,则该互动程序的图像将临时替换JLabel的图标,以表示其处于悬停状态,并在鼠标退出时恢复
  • 如果激活的戳记工具上有互动程序,并且单击了JLabel,则该JLabel的图标将被设置为“永久”激活的戳记互动程序,除非恢复
  • 如果启用了“有网格线”选项,则每个JLabel图标都将通过ImageFactory进行处理,使虚线沿上边缘和左边缘延伸(如图所示,形成网格) 如果更改了缩放级别,则每个JLabel的preferredSize都将设置为可容纳,并且必须在ImageFactory中调整图标的大小(应用的网格线取决于)

在将映射加载到编辑器中时,将创建每个JLabel,并给出其相应的BuffereImage(无论是否为空),然后将其抛出到映射的字段ArrayList中。设置preferredSize使布局看起来正确,并将其添加到MapCanvas(只是一个JPanel)

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

因此,基本上,当JLabel接收到MouseEvent时,会发生以下情况:

  • MouseEvent将源JLabel发送到ActionListener
  • 侦听器使用源JLabel作为键来获取所需的BuffereImage块
  • 然后对BuffereImage区块进行相应的处理(可以是颜色Alpha合成、应用到它的缩放因子、添加到它的网格线,或者这些的组合)

有没有更好的办法?这不会对我2岁的笔记本电脑造成任何明显的影响,但当鼠标与我较旧的台式机上的JLabel交互时,会有非常明显的延迟

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

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

ArrayList和HashMaps是问题所在吗?许多映像操作是问题所在吗


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

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

如果您知道每个
HashMap
s和
ArrayList
s的最大可能大小,您可能会从使用具有初始容量的构造函数中受益这将防止它们使用过多的内存。并将防止因增加容量而可能出现的任何延迟

阅读每种类型文档的前几段也可能对您有所裨益,因为它们可以很好地解释有效使用(例如
HashMap
s loadfactor)

<> P>也可以考虑其他类型的列表和映射(如果您不知道它们的实现方式的不同),例如,代码> LINKEDLIST//COD>比“代码> ARARYLIST/<代码>有更高效的删除和插入操作,但是,随机访问索引要比
ArrayList
慢得多,因为它必须遍历之前的每个索引才能到达所需的索引,而
ArrayList
可以直接访问所需的索引

然而,很难猜测你根据这些建议所做的任何改变会有多明显