java - 如何改进数十万个项目的for循环?-- 格式化这么多项目的实际问题
问题描述
我有一个包含 300k+ 元素的树形图,我需要遍历这些元素。我原以为它需要一段时间,但它已经到了看起来像是挂起的地步。我插入了一个 println 语句来跟踪我在其中的位置,实际上,当它到达某些点时,它会暂停一到三秒,然后继续。最终(大约 140k 英寸),它完全停止,然后最终自行终止程序。
我正在尝试为我的项目制作树图创建者和查看器。这是一棵 n-tree,但并非所有分支都会有 n-children。然而,为了按照我的需要对齐它,我需要创建一个完整的树,其中所有可能的子节点都达到指定的大小,然后对其进行迭代以检查大小、更改大小、位置和存在。
//ArrayList<Button[]> buttons is passed in
double width = 0;
double height = 0;
Group g = new Group();
Scene s = new Scene(g);
Button[] array = buttons.get(buttons.size() - 1);
int temp = 1;
for(int i = 0; i < array.length; ++i) {
Button b = array[i];
g.getChildren().add(b);
g.applyCss();
g.layout();
width = width > b.getWidth() ? width : b.getWidth();
height = height > b.getHeight() ? height : b.getHeight();
g.getChildren().remove(b);
System.out.println(temp++);
}
编辑(因为我忘了说这个):我首先尝试了一个 for-each 循环,但它有同样的问题,换成这个看看它是否更好并收到相同的结果
编辑:延迟的主要来源来自applyCSS()或layout(),但我仍然怀疑,因为它在看似随机的低至16k的地方暂停,并且在其余部分中偶尔暂停,直到它在170k和300k之间消失
编辑:我通过忽略占位符按钮制定了自己的解决方案,因此忽略了树中的几乎所有内容,但我保持开放,希望有人知道实际的解决方案并发布它,以便其他人也可以受益。目前的问题是弄清楚如何应用CSS和布局数十万个节点以确定它们的大小
解决方案
不要考虑 for-each 循环与普通循环、数组列表和类似的微优化,它们最多可能会给你一毫秒。迭代一百万个元素非常便宜,重要的是你用它们做什么。
它看起来像内存泄漏,你的内存消耗似乎增加了,然后 GC 开始导致一个微小的暂停,但它无法回收足够的内存,所以它以越来越高的频率被调用,最后进程因为它是徒劳的而死亡。
也许一个添加然后删除的按钮会保留一些额外的信息,也许是场景或组。
尝试java -verbose:gc ...
或从外部观察内存。在调试器中,检查组件以找出在g.getChildren().remove(b)
.
考虑重新创建组件,可能每 1000秒使用一个新的Scene
/或完全删除按钮。请注意,长期不应存在于可视元素中,因此在需要时从您的数据重新创建按钮应该是微不足道的(尚不可见是一种廉价的数据结构(并且创建速度非常快),而屏幕上的按钮可能拥有更多资源)。Group
Button
Button
推荐阅读
- javascript - 仅在 javascript 中显示前 n 个复选框/元素
- javascript - 动态样式组件标签名称
- c# - 从 SQL Server Express 读取数据时出错
- windows - Gitlab windows Runner lastcontact 显示从不
- python - 从通配符列表中使用 glob 复制多个文件
- c++ - 你怎么能 emplace_back 错误的类型?
- ios - dyld:库未加载:Xcode 更新后的@rpath/libswiftCore.dylib
- asp.net - 提供两个带有一个标头/HTTP 事务的 .csv 文件
- javascript - 动态文件夹内容的图像自动滑块
- c# - 为什么 TcpListener 不监听?