首页 > 解决方案 > 如何改进数十万个项目的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和布局数十万个节点以确定它们的大小

标签: javaarraysperformancefor-looparraylist

解决方案


不要考虑 for-each 循环与普通循环、数组列表和类似的微优化,它们最多可能会给你一毫秒。迭代一百万个元素非常便宜,重要的是你用它们做什么。

它看起来像内存泄漏,你的内存消耗似乎增加了,然后 GC 开始导致一个微小的暂停,但它无法回收足够的内存,所以它以越来越高的频率被调用,最后进程因为它是徒劳的而死亡。

也许一个添加然后删除的按钮会保留一些额外的信息,也许是场景或组。

尝试java -verbose:gc ...或从外部观察内存。在调试器中,检查组件以找出在g.getChildren().remove(b).


考虑重新创建组件,可能每 1000秒使用一个新的Scene/或完全删除按钮。请注意,长期不应存在于可视元素中,因此在需要时从您的数据重新创建按钮应该是微不足道的(尚不可见是一种廉价的数据结构(并且创建速度非常快),而屏幕上的按钮可能拥有更多资源)。GroupButtonButton


推荐阅读