哪个更快:x 个整数数组或包含 x 个整数字段的对象?
Which one is faster: an array of x integers or an object containing x integer fields?
到目前为止,在我正在编写的程序中,我一直使用数组来存储有关线段的数据。为了这个问题,我们假设这些数组只包含定义开始 (x1, y1) 和结束 (x2, y2) 坐标的整数。
Integer[] lineData = {x1, y1, x2, y2};
在我的程序中,我需要使用for循环不断地对多个这样的数组中包含的数据进行操作。
在编写程序的过程中,我无数次意识到我需要有关这些段的更多数据。结果,我向数组添加了元素,数组变大了,例如:
Integer[] lineData = {x1, y1, x2, y2, slope, red, green, blue, width};
这变得很难管理,因为我需要记住每个整数数据的位置才能对其执行操作,并且实现对数组的更改非常繁琐,例如交换两个元素的位置,因为我需要在对元素执行操作的程序的每个部分中更新元素的索引。
这让我想到了创建一个 lineData class 的可能显而易见的想法,其中包含整数作为其字段:
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 class 的字段将比访问和更改数组中的元素慢。我担心的原因是相信数组的存在是有原因的。
使用 lineList class 的另一个论点是需要存储关于线段的数据,这些数据不是整数,而是字符串、布尔值和其他自定义对象。
但是,请忽略该参数。我想将整数数组与仅包含整数字段的 class 进行比较。
综上所述,我的问题是:
哪个更快:x 个整数数组还是包含 x 个整数字段的对象?
当您过去遇到所描述的问题时,您是如何解决的?如果使用带字段的对象比使用数组慢,您是否仍决定使用带字段的对象?为什么?
请注意这些数组的数量非常多,因此将数组更改为具有字段的对象会创建大量循环的实例化对象 - 也许这会影响性能?
非常感谢您的帮助!
您是否考虑过使用列表或集合之类的东西?
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
你可以做的技巧列表还在继续,你确定你使用了正确的数据结构吗?
Array
s 用于存储 数量未知 的实例数量,或者您必须 迭代 对实例执行相同的操作。
因此,数组最好包含相同(语义)类型 的对象。在这种情况下这是不正确的,您在坐标后存储线宽。虽然技术上没问题,但是维护起来会比较麻烦
所以从开发的角度来说,最好是创建一个class来存储线段,然后将不同的线段存储在一个数组中。
所以您可能需要的是一个 LineData[]
数组。在每个元素中存储一行数据的位置。
从性能的角度来看,差别不大。
- 通过方法访问字段:在这种情况下,您首先调用方法创建开销(调用堆栈框架)以及空检查,但是访问字段本身是快,因为Java提前知道字段的位置。
- 访问public字段:一般来说这不是一个好主意。优点是你只需要对对象执行
null
检查。
- 访问数组元素。在这种情况下,会进行两项检查:对数组进行
null
检查和 index
检查(如果优化(并且在具有合理指令集的机器上),则可以在一次操作中完成此索引检查) .
但是,如果您事先不确定线段的数量,您最好使用 List<LineData>
实例,因此 LinkedList
或 ArrayList
。
首先,我想说如果你只处理整数并且你努力性能,那么你当然应该使用int[]
而不是 Integer[]
:
int[]
是一个包含原生整数数组(4 字节)的单个对象
Integer[]
是Integer
class的数组,意思是全部实例化时,对象的个数与数组的长度一样多。
现在回答你的问题。
坦率地说,就您的设计和性能问题而言,您应该选择 LineData
class。我看不出有任何理由在数组中实现 伪 对象。从概念上讲,将 slope
、color
、x
、y
等不同性质的东西存储在同一个数组中是没有意义的。数组(甚至原生)是一种集合,因此应该包含具有相同性质的值。
关于性能,我想说编译器可以很容易地优化对象上的 getter 和 setter。
使用 LineData
class 来存储您的对象适合、可读并且肯定比将所有数据连续保存在同一个数组中快。
因为在那种情况下,对于每一行详细信息,您必须迭代数组两次,第一次到达每行详细信息的开头,第二次循环遍历这些详细信息,这 非常昂贵 和 不需要的.
对于结构性能,使用 Java 集合(List、Set 和 Map)来存储这些行比使用数组要好,要决定使用哪一个,我们需要知道它们之间的区别它们以及何时使用它们中的每一个:
- 如果您需要通过索引频繁访问元素,那么 List 是一个不错的选择。它的实施例如如果您知道索引,ArrayList 提供更快的访问。
- 如果你想存储元素并希望它们保持插入集合的顺序,那么再次使用 List,因为 List 是一个有序集合并保持插入顺序。
- 如果您想创建唯一元素的集合并且不想要任何重复项,那么选择任何 Set 实现,例如HashSet、LinkedHashSet 或 TreeSet。所有 Set 实施都遵循一般合同,例如独特性,但也添加附加功能,例如TreeSet 是一个 SortedSet,存储在 TreeSet 上的元素可以使用 Java 中的 Comparator 或 Comparable 进行排序。 LinkedHashSet 也维护插入顺序。
- 如果您以键和值的形式存储数据,那么 Map 是最佳选择。您可以根据您的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。为了在前两个之间进行选择,请参阅 Java.
中 HashSet 和 HashMap 之间的区别
而且我认为在你的情况下你只需要使用 List of LineData objects (List<LineData>
) 来获得更快地访问其元素:
到目前为止,在我正在编写的程序中,我一直使用数组来存储有关线段的数据。为了这个问题,我们假设这些数组只包含定义开始 (x1, y1) 和结束 (x2, y2) 坐标的整数。
Integer[] lineData = {x1, y1, x2, y2};
在我的程序中,我需要使用for循环不断地对多个这样的数组中包含的数据进行操作。
在编写程序的过程中,我无数次意识到我需要有关这些段的更多数据。结果,我向数组添加了元素,数组变大了,例如:
Integer[] lineData = {x1, y1, x2, y2, slope, red, green, blue, width};
这变得很难管理,因为我需要记住每个整数数据的位置才能对其执行操作,并且实现对数组的更改非常繁琐,例如交换两个元素的位置,因为我需要在对元素执行操作的程序的每个部分中更新元素的索引。
这让我想到了创建一个 lineData class 的可能显而易见的想法,其中包含整数作为其字段:
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 class 的字段将比访问和更改数组中的元素慢。我担心的原因是相信数组的存在是有原因的。
使用 lineList class 的另一个论点是需要存储关于线段的数据,这些数据不是整数,而是字符串、布尔值和其他自定义对象。
但是,请忽略该参数。我想将整数数组与仅包含整数字段的 class 进行比较。
综上所述,我的问题是:
哪个更快:x 个整数数组还是包含 x 个整数字段的对象? 当您过去遇到所描述的问题时,您是如何解决的?如果使用带字段的对象比使用数组慢,您是否仍决定使用带字段的对象?为什么?
请注意这些数组的数量非常多,因此将数组更改为具有字段的对象会创建大量循环的实例化对象 - 也许这会影响性能?
非常感谢您的帮助!
您是否考虑过使用列表或集合之类的东西?
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
你可以做的技巧列表还在继续,你确定你使用了正确的数据结构吗?
Array
s 用于存储 数量未知 的实例数量,或者您必须 迭代 对实例执行相同的操作。
因此,数组最好包含相同(语义)类型 的对象。在这种情况下这是不正确的,您在坐标后存储线宽。虽然技术上没问题,但是维护起来会比较麻烦
所以从开发的角度来说,最好是创建一个class来存储线段,然后将不同的线段存储在一个数组中。
所以您可能需要的是一个 LineData[]
数组。在每个元素中存储一行数据的位置。
从性能的角度来看,差别不大。
- 通过方法访问字段:在这种情况下,您首先调用方法创建开销(调用堆栈框架)以及空检查,但是访问字段本身是快,因为Java提前知道字段的位置。
- 访问public字段:一般来说这不是一个好主意。优点是你只需要对对象执行
null
检查。 - 访问数组元素。在这种情况下,会进行两项检查:对数组进行
null
检查和index
检查(如果优化(并且在具有合理指令集的机器上),则可以在一次操作中完成此索引检查) .
但是,如果您事先不确定线段的数量,您最好使用 List<LineData>
实例,因此 LinkedList
或 ArrayList
。
首先,我想说如果你只处理整数并且你努力性能,那么你当然应该使用int[]
而不是 Integer[]
:
int[]
是一个包含原生整数数组(4 字节)的单个对象Integer[]
是Integer
class的数组,意思是全部实例化时,对象的个数与数组的长度一样多。
现在回答你的问题。
坦率地说,就您的设计和性能问题而言,您应该选择 LineData
class。我看不出有任何理由在数组中实现 伪 对象。从概念上讲,将 slope
、color
、x
、y
等不同性质的东西存储在同一个数组中是没有意义的。数组(甚至原生)是一种集合,因此应该包含具有相同性质的值。
关于性能,我想说编译器可以很容易地优化对象上的 getter 和 setter。
使用 LineData
class 来存储您的对象适合、可读并且肯定比将所有数据连续保存在同一个数组中快。
因为在那种情况下,对于每一行详细信息,您必须迭代数组两次,第一次到达每行详细信息的开头,第二次循环遍历这些详细信息,这 非常昂贵 和 不需要的.
对于结构性能,使用 Java 集合(List、Set 和 Map)来存储这些行比使用数组要好,要决定使用哪一个,我们需要知道它们之间的区别它们以及何时使用它们中的每一个:
- 如果您需要通过索引频繁访问元素,那么 List 是一个不错的选择。它的实施例如如果您知道索引,ArrayList 提供更快的访问。
- 如果你想存储元素并希望它们保持插入集合的顺序,那么再次使用 List,因为 List 是一个有序集合并保持插入顺序。
- 如果您想创建唯一元素的集合并且不想要任何重复项,那么选择任何 Set 实现,例如HashSet、LinkedHashSet 或 TreeSet。所有 Set 实施都遵循一般合同,例如独特性,但也添加附加功能,例如TreeSet 是一个 SortedSet,存储在 TreeSet 上的元素可以使用 Java 中的 Comparator 或 Comparable 进行排序。 LinkedHashSet 也维护插入顺序。
- 如果您以键和值的形式存储数据,那么 Map 是最佳选择。您可以根据您的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。为了在前两个之间进行选择,请参阅 Java. 中 HashSet 和 HashMap 之间的区别
而且我认为在你的情况下你只需要使用 List of LineData objects (List<LineData>
) 来获得更快地访问其元素: