【问题标题】:Which one is faster: an array of x integers or an object containing x integer fields?哪个更快:x 个整数的数组或包含 x 个整数字段的对象?
【发布时间】:2015-03-02 11:08:07
【问题描述】:

到目前为止,在我正在编写的程序中,我一直在使用数组来存储有关线段的数据。为了这个问题,我们假设这些数组只包含定义 start (x1, y1) 和 end (x2, y2) 坐标的整数。

Integer[] lineData = {x1, y1, x2, y2};

在我的程序中,我需要使用 for 循环不断地对多个此类数组中包含的数据执行操作。

在编写程序的过程中,我多次意识到我需要更多关于这些段的数据。结果,我向数组中添加了元素,数组变大了,例如:

Integer[] lineData = {x1, y1, x2, y2, slope, red, green, blue, width};

这变得很难管理,因为我需要记住每个整数数据的位置才能对其执行操作,并且实现对数组的更改非常繁琐,例如交换两个元素的位置,因为我需要更新对它们执行操作的程序的每个部分中元素的索引。

这让我想到了创建一个包含整数作为其字段的 lineData 类的可能显而易见的想法:

public class LineData {

public int x1,y1,x2,y2,slope, red, green, blue, width;

LineData(int x1, int y1, int x2, int y2, int slope, int red, int green, int blue, int width){
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.slope = slope;
    this.red = red;
    this.green = green;
    this.blue = blue;
    this.width = width;
}

public int getX1() {
    return x1;
}

public void setX1(int x1) {
    this.x1 = x1;
}

public int getY1() {
    return y1;
}

public void setY1(int y1) {
    this.y1 = y1;
}

public int getX2() {
    return x2;
}

public void setX2(int x2) {
    this.x2 = x2;
}

public int getY2() {
    return y2;
}

public void setY2(int y2) {
    this.y2 = y2;
}

public int getSlope() {
    return slope;
}

public void setSlope(int slope) {
    this.slope = slope;
}

public int getRed() {
    return red;
}

public void setRed(int red) {
    this.red = red;
}

public int getGreen() {
    return green;
}

public void setGreen(int green) {
    this.green = green;
}

public int getBlue() {
    return blue;
}

public void setBlue(int blue) {
    this.blue = blue;
}

public int getWidth() {
    return width;
}

public void setWidth(int width) {
    this.width = width;
}
}

这看起来是一个很好的解决方案。

不过,我担心的是访问和更改 lineData 类的字段将比访问和更改数组中的元素慢。我担心的原因是相信数组的存在是有原因的。

使用 lineList 类的另一个参数是需要存储有关线段的数据,这些数据不是整数,而是字符串、布尔值和其他自定义对象。

但是,请忽略该论点。我想将整数数组与仅包含整数字段的类进行比较。

总结一下,我的问题是:

哪个更快:由 x 个整数组成的数组还是包含 x 个整数字段的对象? 当您过去遇到所描述的问题时,您是如何解决的?如果使用带字段的对象比使用数组慢,您是否仍然决定使用带字段的对象?为什么?

请考虑到这些数组的数量非常多,因此将数组更改为具有字段的对象会创建大量循环的实例化对象 - 也许这会影响性能?

非常感谢您的帮助!

【问题讨论】:

  • 唯一确定的方法是对其进行基准测试。尽管存储效率可能不同,但总体上将有同样多的对象。另请注意,getter 和 setter 虽然经常被推荐,但不是强制性的。
  • 对象更具可读性,我强烈建议您朝这个方向发展。
  • @DNA 你能告诉我我将如何进行基准测试或指出一些关于该主题的其他资源吗?

标签: java arrays performance class for-loop


【解决方案1】:

首先,我想说的是,如果您只处理整数并且努力进行表演,那么您当然应该使用int[]而不是Integer[]: p>

  • int[] 是一个包含原生整数数组(4 字节)的单个对象
  • Integer[]Integer 类的数组,这意味着当所有对象都被实例化时,与数组长度一样多。

现在谈谈你的问题。 坦率地说,关于您的设计和性能问题,您应该选择 LineData 课程。我看不出有什么好的理由在数组中实现 pseudo 对象。从概念上讲,将 slopecolorxy...等不同性质的东西存储在同一个数组中是没有意义的。数组(甚至是原生数组)是一种集合,然后应该包含具有相同性质的值。

在性能方面,我想说编译器可以轻松优化对象的 getter 和 setter。

【讨论】:

    【解决方案2】:

    您是否考虑过使用列表或集合之类的东西?

    List<Interger> myList = new ArrayList<Integer>();
    
    myList.add(5);
    
    boolean foo = myList.contains(5); // true
    
    foo = myList.contains(6); // false
    
    int size = myList.size(); // 1 
    foo = myList.isEMpty(); //false   
    
    myList.remove(new Integer(5));
    size.size() // 0
    foo = myList.isEmpty(); // true
    

    或者也许你需要一张地图?

    Map myMap<String,Integer> = new HashMap<String, Integer>();
    
    myMap.put("blue", 5);
    myMap.put("red", 6);
    
    int value = myMap.get("red"); // 6
    int size = myMap.size(); //2
    myMap.remove("red");
    size = myMap.sie(); //2
    

    你可以做的技巧列表还在继续,你确定你使用的是正确的数据结构吗?

    【讨论】:

    • 我正在使用数组的 ArrayList 将线段存储在 Curve 类中,但我会研究 HashMaps!
    【解决方案3】:

    Arrays 用于存储数字未知的多个实例,或者您必须迭代实例并执行对它们进行相同的操作

    因此,数组最好包含相同(语义)类型的对象。在这种情况下,这是不正确的,您在坐标之后存储线宽。虽然技术上没有问题,但是会很难维护。

    所以从开发的角度来看,最好创建一个存储线段的类,然后将不同的线段存储在一个数组中。

    所以你可能需要一个LineData[] 数组。您在每个元素中存储一行数据的位置。

    性能的角度来看,差别不大。

    • 通过方法访问字段:在这种情况下,您首先调用方法创建开销(调用堆栈帧)以及空检查,但访问字段本身很快,因为 Java 知道预先确定场地的位置。
    • 访问公共字段:通常不被认为是一个好主意。优点是您只需对对象执行null 检查。
    • 访问数组元素。在这种情况下,会进行两项检查:对数组进行null-check 和index 检查(如果经过优化,可以在一个操作中完成索引检查(并且在具有合理指令集的机器上)。

    但是,如果您事先不确定线段的数量,您最好使用List&lt;LineData&gt; 实例,即LinkedListArrayList

    【讨论】:

    • 那么,如果我理解你的话,性能方面,直接访问和设置字段而不是使用 getter 和 setter 更好吗?另外,我使用 arrayList 将线段数据存储在曲线类中,其中包含线段。
    • @wit221:性能方面是的,但这不是一个好主意。有时您需要牺牲一些性能来换取更易于维护的源代码。
    【解决方案4】:

    使用LineData 类来存储您的对象比将所有数据依次保存在相同的数组。

    因为在这种情况下,对于每行细节,您必须迭代数组两次,第一次到达每行细节的开头,第二次循环遍历那些 非常昂贵 和 不想要的。

    对于结构性能,使用 Java 集合(List、Set 和 Map)来存储这些行比使用 Array 更好,要决定使用哪一个,我们需要知道它们之间的区别以及何时使用它们其中之一:

    1. 如果您需要通过索引频繁访问元素,List 是一种选择。它的实现例如如果您知道索引,ArrayList 提供更快的访问。
    2. 如果您想存储元素并希望它们保持插入到集合中的顺序,请再次使用 List,因为 List 是有序集合并保持插入顺序。
    3. 如果您想创建独特元素的集合并且不希望任何重复,则可以选择任何 Set 实现,例如HashSet、LinkedHashSet 或 TreeSet。所有 Set 实现都遵循一般合同,例如独特性,但还添加了附加功能,例如TreeSet 是一个 SortedSet,存储在 TreeSet 上的元素可以使用 Java 中的 Comparator 或 Comparable 进行排序。 LinkedHashSet 还维护插入顺序。
    4. 如果您以键和值的形式存储数据,那么 Map 是最好的选择。 Hashtable、HashMap、TreeMap 可以根据自己的后续需求进行选择。为了在前两者之间进行选择,请参阅 Java 中 HashSet 和 HashMap 之间的区别。

    我认为在您的情况下,您只需要使用 LineData 对象 (List&lt;LineData&gt;) 的 List 即可更快地访问其元素:

    【讨论】:

      猜你喜欢
      • 2014-01-13
      • 2021-12-17
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 2018-11-17
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      相关资源
      最近更新 更多