在Java中,我应该使用ArrayList<;长期>;还是长[]?

在Java中,我应该使用ArrayList<;长期>;还是长[]?,java,arrays,performance,arraylist,Java,Arrays,Performance,Arraylist,我正在编写一个程序,它接受400个类型的long,并将根据运行时的条件修改其中一些,我想知道是使用ArrayList还是long[] 哪一个使用起来更快?我正在考虑使用long[],因为大小是固定的。当大小固定时,long[]更快,但它允许一个可维护性较差的API,因为它没有实现列表接口 注long[]更快,原因有二: 使用原语longs和not box对象longs(也可以实现更好的缓存性能,因为longs是连续分配的,并且longs不能保证) 阵列更简单、效率更高 然而,为了更简单的可维护性

我正在编写一个程序,它接受400个类型的
long
,并将根据运行时的条件修改其中一些,我想知道是使用
ArrayList
还是
long[]


哪一个使用起来更快?我正在考虑使用
long[]
,因为大小是固定的。

当大小固定时,
long[]
更快,但它允许一个可维护性较差的API,因为它没有实现
列表
接口

long[]
更快,原因有二:

  • 使用原语
    long
    s和not box对象
    long
    s(也可以实现更好的缓存性能,因为
    long
    s是连续分配的,并且
    long
    s不能保证)
  • 阵列更简单、效率更高
  • 然而,为了更简单的可维护性,我会使用
    列表
    ,除非性能在程序的这一部分非常关键


    如果您经常在一个紧密的循环中使用此集合,并且您的分析器说它确实是一个瓶颈,那么我将切换到更高效的
    长[]

    ,就速度而言,对于400个项目的列表几乎不重要。如果您需要动态增长列表,
    ArrayList
    更好;如果大小是固定的,
    long[]
    可能会更好(而且速度会更快,不过在大多数情况下,您可能不会注意到差异)。

    long[]速度更快,占用的内存也更少。阅读“effectivejava”第49项:“更喜欢基本类型而不是盒装基本类型”

    我认为最好使用ArrayList,因为它更易于长期维护。将来,如果阵列的大小增加到400以上,则维护长[]会带来很大的开销,而ArrayList会动态增长,因此您无需担心大小的增加。
    此外,ArrayList比静态数组(long[])更好地处理元素的删除,因为它们会自动重新组织元素,使它们仍然显示为有序元素。
    静态数组在这方面更糟糕。

    在其他答案中没有提到的事情很少:

    • 泛型集合实际上是
      对象
      的集合,或者更好地说,这是Java编译器将利用它的。这是因为
      long[]
      始终保持原样

    • 第一个要点的一个结果是,如果您做的某件事最终将非
      Long
      的内容放入集合中,在某些情况下编译器会让它通过(因为Java类型系统不健全,例如,它将允许您向上转换,然后重新转换为完全不同的类型)

    • 这两种方法的一个更普遍的结果是Java泛型是半生不熟的,在一些不那么简单的情况下,如反射、序列化等,可能会让您“惊讶”。事实上,使用普通数组比使用泛型更安全


    包tld.example;
    导入java.util.List;
    导入java.util.ArrayList;
    课例{
    静态无效测试阵列(长[]长){
    System.out.println(“testArray”);
    }
    静态void testGeneric(列表长度){
    System.out.println(“testGeneric”);
    }
    @抑制警告(“未选中”)
    公共静态void main(字符串…参数){
    List fakeLongs=new ArrayList();
    List mischiefManaged=(List)(Object)fakeLongs;
    添加(新对象());
    //此调用成功并打印值。
    //我们可能会在这个函数中插入错误的类型
    //但它仍然没有被注意到
    测试通用(fakeLongs);
    long[]realLongs=新长[1];
    //这将失败,因为无法执行此强制转换
    //尽管编译器认为它是。
    Object[]forgedLongs=(Object[])(Object)realLongs;
    forgedLongs[0]=新对象();
    testArray(雷隆);
    }
    }
    
    这个例子有点做作,因为很难想出一个简短的、令人信服的例子,但是相信我,在不那么琐碎的情况下,当你不得不使用反射和不安全的强制转换时,这是很有可能的


    现在,你必须考虑到,除了合理的东西外,还有一个传统。每个社区都有一套自己的习俗和传统。有很多肤浅的信念,比如这里所说的。当有人声称实现
    List
    API是一种无条件的善,如果这没有发生,那么它一定是坏的。。。这不仅仅是一个占主导地位的观点,这也是绝大多数Java程序员所相信的。毕竟,这没什么大不了的,Java作为一种语言还有很多其他的缺点。。。因此,如果您想确保面试的安全,或者只是想避免与其他Java程序员发生冲突,那么就使用Java泛型,不管是什么原因。但是如果你不喜欢它——好吧,也许可以用其他语言;)

    为什么不使用处理基元类型的众多列表实现之一?例如。它可以像javaslist一样使用,但基于长[]数组。所以你们双方都有优势


    HPPC简要介绍了一些库:

    速度不是你的问题。使用ArrayList:为什么?因为它将自动增长,是一个性能更好的集合!(我说速度/性能不是问题;如果是,那么你会有一些性能基准来证明我错了!在那之前,不要担心。)使用
    long[]
    如果大小固定,你可以使用long[]如果有一些数据,并且有大量数千个数据,则切换到arralist以获得更好的性能和安全性。@ManishNagar“切换到arralist以获得更好的性能和安全性”安全性?如何使用
    ArrayList
    提供更好的安全性?@ManishNagar以及它如何为
    package tld.example;
    
    import java.util.List;
    import java.util.ArrayList;
    
    class Example {
    
        static void testArray(long[] longs) {
            System.out.println("testArray");
        }
    
        static void testGeneric(List<Long> longs) {
            System.out.println("testGeneric");
        }
    
        @SuppressWarnings("unchecked")
        public static void main(String... arguments) {
            List<Long> fakeLongs = new ArrayList<Long>();
            List<Object> mischiefManaged = (List<Object>)(Object)fakeLongs;
            mischiefManaged.add(new Object());
            // this call succeeds and prints the value.
            // we could sneak in a wrong type into this function
            // and it remained unnoticed
            testGeneric(fakeLongs);
    
            long[] realLongs = new long[1];
            // this will fail because it is not possible to perform this cast
            // despite the compiler thinks it is.
            Object[] forgedLongs = (Object[])(Object)realLongs;
            forgedLongs[0] = new Object();
            testArray(realLongs);
        }
    }