从 ArrayList 中删除多个元素的快速算法

2023-12-12

假设 ArrayList 的大小为 n。

就我而言,我经常需要从 ArrayList 中删除 1 到 n 个具有不同索引的元素。

通过使用 VisualVM Profiler,我发现 ArrayList.remove() 花费了大约 90% 的运行时间。

所以我想提高删除的性能。我想知道是否可以加速。

这是一个最小的例子:

public void testArrayListRemove() {
        List list = new ArrayList();
        int[] indexes = new int[] { 1, 2, 4, 10, 100, 1000 };
        for (int i = 0; i < 100000; i++) {
            list.add(i);
        }
        for (int i = indexes.length - 1; i >= 0; i--) {
            list.remove(indexes[i]);
        }
    }

我能想到的想法是将那些要删除的元素交换到最后并在那里删除它们,这样ArrayList.remove()就不需要进行system.arraycopy。我不确定这是否真的有效。

注意:ArrayList.remove(i) 当 i 不是最后一个元素时,它将执行 System.arraycopy 来移动元素。

如果您能提供解决我的问题的想法,我将不胜感激。您可以评论我将元素交换到最后的天真想法,或者甚至更好地提供除我的想法之外的更高级的算法。

Thanks.


你应该看看GapList – 闪电般快速的列表实现

来自文章:


GapList简介

为了解决所带来的问题,我们引入了 GapList 作为java.util.List界面。作为主要功能,GapList 提供

  • 通过索引高效访问元素
  • 在列表的头部和尾部插入恒定时间
  • 利用应用程序中常见的引用局部性

让我们看看如何实现 GapList 来提供这些功能。

如果我们比较 ArrayList 如何处理不同类型的插入,我们可以很快找到一个解决方案来保证在列表的开头和结尾快速插入。

我们不是移动所有元素以在索引 0 处获得空间,而是将现有元素保留在原处,并在有剩余空间时将元素写入已分配数组的末尾。 所以我们基本上使用数组作为一种旋转缓冲区。

GapList1

为了以正确的顺序访问元素,我们必须记住第一个元素的起始位置,并使用模运算从逻辑索引计算物理索引:

physIndex = (start + index) % capacity

为了利用引用的局部性,我们允许在列表元素的存储中包含间隙。由后备阵列中未使用的插槽形成的间隙可以位于列表中的任何位置。最多有一个间隙,但也可以没有。

这个间隙可以帮助您利用列表引用的局部性,因此如果您将一个元素添加到列表的中间,则后续添加到中间的速度将会很快。

Middle

如果 GapList 没有间隙,则在需要时创建一个。如果间隙位置错误,则将其移动。但如果操作发生在彼此附近,则只需复制很少的数据。

GapList 还允许在开头和结尾删除元素,而无需移动任何元素。

Remove

中间删除的处理方式与插入类似:如果不再需要,现有间隙可能会被移动或消失。


这是一个小示例代码:

package rpax.stackoverflow.q24077045;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import org.magicwerk.brownies.collections.GapList;

public class Q24077045 {

    static int LIST_SIZE = 500000;

    public static void main(String[] args) {
        long a1, b1, c1 = 0, a2, b2, c2 = 0;
        int[] indexes = generateRandomIndexes(10000);

        a2 = System.currentTimeMillis();
        List<Integer> l2 = testArrayListRemove2(indexes);
        if (l2.size() < 1)
            return;
        b2 = System.currentTimeMillis();
        c2 = b2 - a2;

        a1 = System.currentTimeMillis();
        List<Integer> l = testArrayListRemove(indexes);
        if (l.size() < 1)
            return;
        b1 = System.currentTimeMillis();
        c1 = b1 - a1;

        System.out.println("1 : " + c1);
        System.out.println("2 : " + c2);

        System.out.println("Speedup : "+ c1 * 1.00 / c2+"x");

    }

    static int[] generateRandomIndexes(int number) {
        int[] indexes = new int[number];
        for (int i = 0; i < indexes.length; i++)
        {
            indexes[i] = ThreadLocalRandom.current().nextInt(0, LIST_SIZE);
        }
        Arrays.sort(indexes);
        return indexes;
    }

    public static List<Integer> testArrayListRemove(int[] indexes) {
        List<Integer> list = new ArrayList<Integer>(LIST_SIZE);

        for (int i = 0; i < LIST_SIZE; i++)
            list.add(i);

        for (int i = indexes.length - 1; i >= 0; i--)
            list.remove(indexes[i]);
        return list;
    }

    public static List<Integer> testArrayListRemove2(int[] indexes) {

        List<Integer> list = GapList.create(LIST_SIZE);

        for (int i = 0; i < LIST_SIZE; i++)
            list.add(i);

        for (int i = indexes.length - 1; i >= 0; i--)
            list.remove(indexes[i]);
        return list;
    }

}

我的笔记本电脑速度快了大约 10 倍。这似乎是一个很好的替代方案ArrayList.

Disclaimer: This is not a performance analisis. It is only an illustrative example.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 ArrayList 中删除多个元素的快速算法 的相关文章

  • 如何在 JFace 的 TableViewer 中创建复选框?

    我创建了一个包含两列的 tableViewer 我想将其中一列设为复选框 为此 我创建了一个 CheckBoxCellEditor 但我不知道为什么它不起作用 名为 tableName 的列显示其值正常 色谱柱规格如下 String COL
  • 在浏览器中点击应用程序时播放框架挂起

    我正在 Play 中运行一个应用程序activator run 也许 5 次中有 3 次 它会挂起 当我去http localhost 9000 它就永远坐在那里旋转 我看到很多promise timed out错误也 我应该去哪里寻找这个
  • java中删除字符串中的特殊字符?

    如何删除字符串中除 之外的特殊字符 现在我用 replaceAll w s 它删除了所有特殊字符 但我想保留 谁能告诉我我该怎么办 Use replaceAll w s 我所做的是将下划线和连字符添加到正则表达式中 我添加了一个 连字符之前
  • HDFS:使用 Java / Scala API 移动多个文件

    我需要使用 Java Scala 程序移动 HDFS 中对应于给定正则表达式的多个文件 例如 我必须移动所有名称为 xml从文件夹a到文件夹b 使用 shell 命令我可以使用以下命令 bin hdfs dfs mv a xml b 我可以
  • 如何为 Gson 编写自定义 JSON 反序列化器?

    我有一个 Java 类 用户 public class User int id String name Timestamp updateDate 我收到一个包含来自 Web 服务的用户对象的 JSON 列表 id 1 name Jonas
  • 如何在jsp代码中导入java库?

    我有以下jsp代码 我想添加 java io 等库 我怎样才能做到这一点
  • Microsoft Graph 身份验证 - 委派权限

    我可以使用 Microsoft Graph 访问资源无需用户即可访问 https developer microsoft com en us graph docs concepts auth v2 service 但是 此方法不允许我访问需
  • 序列化对象以进行单元测试

    假设在单元测试中我需要一个对象 其中所有 50 个字段都设置了一些值 我不想手动设置所有这些字段 因为这需要时间而且很烦人 不知何故 我需要获得一个实例 其中所有字段都由一些非空值初始化 我有一个想法 如果我要调试一些代码 在某个时候我会得
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • 归并排序中的递归:两次递归调用

    private void mergesort int low int high line 1 if low lt high line 2 int middle low high 2 line 3 mergesort low middle l
  • 检查 protobuf 消息 - 如何按名称获取字段值?

    我似乎无法找到一种方法来验证 protobuf 消息中字段的值 而无需显式调用其 getter 我看到周围的例子使用Descriptors FieldDescriptor实例到达消息映射内部 但它们要么基于迭代器 要么由字段号驱动 一旦我有
  • Tomcat 6找不到mysql驱动

    这里有一个类似的问题 但关于类路径 ClassNotFoundException com mysql jdbc Driver https stackoverflow com questions 1585811 classnotfoundex
  • 将 JSON 参数从 java 发布到 sinatra 服务

    我有一个 Android 应用程序发布到我的 sinatra 服务 早些时候 我无法读取 sinatra 服务上的参数 但是 在我将内容类型设置为 x www form urlencoded 之后 我能够看到参数 但不完全是我想要的 我在
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • Java - 不要用 bufferedwriter 覆盖

    我有一个程序可以将人员添加到数组列表中 我想做的是将这些人也添加到文本文件中 但程序会覆盖第一行 因此这些人会被删除 如何告诉编译器在下一个空闲行写入 import java io import java util import javax
  • 将 JTextArea 内容写入文件

    我在 Java Swing 中有一个 JTextArea 和一个 提交 按钮 需要将textarea的内容写入一个带有换行符的文件中 我得到的输出是这样的 它被写为文件中的一个字符串 try BufferedWriter fileOut n
  • 将2-3-4树转换为红黑树

    我正在尝试将 2 3 4 树转换为 java 中的红黑树 但我无法弄清楚它 我将这两个基本类编写如下 以使问题简单明了 但不知道从这里到哪里去 public class TwoThreeFour
  • com.jcraft.jsch.JSchException:身份验证失败

    当我从本地磁盘上传文件到远程服务器时 出现这样的异常 com jcraft jsch JSchException Auth fail at org apache tools ant taskdefs optional ssh Scp exe
  • javax.persistence.Table.indexes()[Ljavax/persistence/Index 中的 NoSuchMethodError

    我有一个 Play Framework 应用程序 并且我was使用 Hibernate 4 2 5 Final 通过 Maven 依赖项管理器检索 我决定升级到 Hibernate 4 3 0 Final 成功重新编译我的应用程序并运行它
  • Swagger/Openapi-Annotations:如何使用 $ref 生成 allOf?

    我正在生成 Rest 端点 包括添加OpenAPI Swagger对生成的代码进行注释 虽然它对于基本类型运行得很好 但我在自定义类方面遇到了一些问题 现在我有很多自定义类的重复架构条目 使用 Schema 实现 MyClass class

随机推荐

  • 如何覆盖 CSS 类的属性以避免复制和重命名样式

    我对 CSS3 相当陌生 我希望能够执行以下操作 当我将一个类添加到元素中时 它会覆盖该特定元素中使用的另一个类的属性 假设我有 a class left carousel control href carousel 我希望能够添加一个名为
  • UIImageView动画消耗内存太多

    我的记忆和动画图像有问题 首先 我正在使用 ARC 在我的初始屏幕上 我有大约 60 个要制作动画的图像 我正在使用此代码进行动画 NSMutableArray images NSMutableArray alloc init int an
  • 常量文件中的 codeigniter base_url

    目前我通过以下方式显示图像 img src USER UPLOAD URL 在 application config constants php 中定义 define USER UPLOAD URL uploads user uploads
  • 使用 XSLT 将输入 XML 转换为其他 XML

    我是初学者 想学习 XSLT 我遇到了使用 XSLT 将输入 XML 文件转换为另一个 XML 文件的问题 我的输入 XML 文件
  • 为什么React-router在url改变时不重新渲染页面也不更新数据?

    我正在 React 中构建一个项目 该项目通过自定义挂钩从 API 检索数据 一旦检索到数据 它就会显示卡片 通过单击它们可以打开描述性页面 到这里一切都好 App js
  • 如何从 WebMatrix 2 Beta 中的 vsdoc 文件引用获取 JavaScript Intellisense?

    我将 JavaScript 文件从 Visual Studio 复制到新的 WebMatrix 2 Beta 项目 结果发现 vsdoc 文件没有用于 JavaScript Intellisense
  • Android背景隐藏子视图文本

    我有一个简单的 LinearLayout 当我添加安卓 背景对于 LinearLayout TextView不再可见 我不明白什么
  • PHP CSV 字符串到数组

    我正在尝试将 CSV 字符串解析为 PHP 中的数组 CSV 字符串具有以下属性 Delimiter Enclosure New line r n 示例内容 12345 Computers Acer 4 Varta 5 93 1 0 04
  • Oracle WITH 和 MATERIALIZE 提示充当函数的自主事务

    在 Oracle 12c 中 如果我在查询中调用在 WITH AS 部分中使用 MATERIALIZE 提示的函数 则该函数调用的行为类似于自治事务 DROP TABLE my table CREATE TABLE my table my
  • 使用 WPF 自定义控件库 (.NET Framework) 中普通 WPF 项目中的 App.xaml

    我有一个 WPF 项目App xaml 不是资源字典 带有一些材料设计的东西和一个 ViewModelLocator MVVM 如下所示
  • 如何在 JGit 中编写 git log --stat 命令

    我有以下 git 命令 git log stat 1000 all gt gitstat log 在 JGit 中可以实现这一点吗 如果是 在 JGit 中编写此代码的等效方法是什么 为了访问存储库的历史记录 JGit 提供了RevWalk
  • 使用 Python 每 64 个字符插入一个换行符

    使用 Python 我需要每 64 个字符向字符串中插入一个换行符 在 Perl 中这很简单 s 64 1 n 如何使用 Python 中的正则表达式来完成此操作 有没有更Pythonic的方法来做到这一点 与 Perl 中相同 但使用反斜
  • 调度 Redux 操作是否被视为昂贵?

    我已经使用 React Redux Typescript 堆栈有一段时间了 到目前为止我很喜欢它 然而 由于我对 Redux 还很陌生 所以我一直想知道这个特定的话题 调度 Redux 操作 和 thunk 是否被认为是昂贵的操作并且应该谨
  • struct 是 Racket 中的宏吗?

    我记得我在某处读到它不是宏 而是内置于核心语言中的 类似的事情 我不确定 因为我已经记不起我是从哪里读到的了 也是如此structRacket 中是否有宏 如果不是 为什么它被内置到核心语言中 一个宏 struct rkthas defin
  • PHP:使用 PDO 从 MySQL 数据库输出 utf8 时出现问题

    dbo new PDO mysql host localhost dbname database databaseuser databasepassword array PDO MYSQL ATTR INIT COMMAND gt SET
  • Oracle:模糊查找

    我正在加载一个表来查找员工表 但是 有时源文件和员工表中的名称不正确匹配 Employee table Employee Name Paul Jaymes Source File Paul James 我想要这个匹配 可能有什么解决办法 U
  • 小阵列最快的偏移读取

    为了速度 我想读取第 9 个寄存器中的值引用的 8 个寄存器之一 我认为执行此操作的最快方法是使用 3 个条件跳转 检查第 9 个中的 3 位 登记 这应该比使用偏移量执行此操作的标准方法具有更短的延迟 内存读取 但这仍然需要至少 6 个时
  • 如何将基类型列表转换为派生类型列表

    从派生类到基类 似乎存在许多相反的问题 但我的问题是如何将基类型列表转换为派生类型列表 public class MyBase public int A public class MyDerived MyBase public int B
  • 删除空格和句点

    我无法让这个正则表达式工作 4 182 ex number period 2 blank spaces 3 numbers blank space 2 characters 正则表达式语法应返回 4182 并删除句点 空格和字符 你能帮我吗
  • 从 ArrayList 中删除多个元素的快速算法

    假设 ArrayList 的大小为 n 就我而言 我经常需要从 ArrayList 中删除 1 到 n 个具有不同索引的元素 通过使用 VisualVM Profiler 我发现 ArrayList remove 花费了大约 90 的运行时