我必须在内存中保留数千个字符串,以便在Java中串行访问。我应该把它们存储在数组中还是应该使用某种列表?
由于数组将所有数据保存在一个连续的内存块中(与list不同),使用数组存储数千个字符串会导致问题吗?
我必须在内存中保留数千个字符串,以便在Java中串行访问。我应该把它们存储在数组中还是应该使用某种列表?
由于数组将所有数据保存在一个连续的内存块中(与list不同),使用数组存储数千个字符串会导致问题吗?
当前回答
不要在没有适当基准测试的情况下陷入优化的陷阱。正如其他人建议的那样,在做出任何假设之前使用分析器。
您所列举的不同数据结构具有不同的用途。列表在开头和结尾插入元素时非常有效,但在访问随机元素时却很困难。数组具有固定的存储,但提供快速的随机访问。最后,ArrayList通过允许数组增长来改进与数组的接口。通常,要使用的数据结构应该由如何访问或添加存储的数据来决定。
About memory consumption. You seem to be mixing some things. An array will only give you a continuous chunk of memory for the type of data that you have. Don't forget that java has a fixed data types: boolean, char, int, long, float and Object (this include all objects, even an array is an Object). It means that if you declare an array of String strings [1000] or MyObject myObjects [1000] you only get a 1000 memory boxes big enough to store the location (references or pointers) of the objects. You don't get a 1000 memory boxes big enough to fit the size of the objects. Don't forget that your objects are first created with "new". This is when the memory allocation is done and later a reference (their memory address) is stored in the array. The object doesn't get copied into the array only it's reference.
其他回答
在存储字符串对象的情况下,数组还是列表的选择并不那么重要(考虑到性能)。因为数组和列表存储的都是字符串对象引用,而不是实际对象。
如果字符串的数量几乎是常数,则使用数组(或ArrayList)。但如果数字变化太大,那么你最好使用LinkedList。 如果有(或将会)需要在中间添加或删除元素,那么你当然必须使用LinkedList。
Java的方式是,您应该考虑哪种数据抽象最适合您的需求。记住,在Java中,List是抽象的数据类型,而不是具体的数据类型。您应该将字符串声明为List,然后使用ArrayList实现初始化它。
List<String> strings = new ArrayList<String>();
抽象数据类型和特定实现的分离是面向对象编程的一个关键方面。
An ArrayList implements the List Abstract Data Type using an array as its underlying implementation. Access speed is virtually identical to an array, with the additional advantages of being able to add and subtract elements to a List (although this is an O(n) operation with an ArrayList) and that if you decide to change the underlying implementation later on you can. For example, if you realize you need synchronized access, you can change the implementation to a Vector without rewriting all your code.
事实上,ArrayList是专门为在大多数情况下替换低级数组构造而设计的。如果Java是今天设计的,那么完全有可能将数组完全排除在外,转而使用数组列表结构。
由于数组将所有数据保存在一个连续的内存块中(与list不同),使用数组存储数千个字符串会导致问题吗?
In Java, all collections store only references to objects, not the objects themselves. Both arrays and ArrayList will store a few thousand references in a contiguous array, so they are essentially identical. You can consider that a contiguous block of a few thousand 32-bit references will always be readily available on modern hardware. This does not guarantee that you will not run out of memory altogether, of course, just that the contiguous block of memory requirement is not difficult to fufil.
列表比数组慢。如果需要效率,请使用数组。如果你需要灵活性,使用列表。
我同意在大多数情况下,您应该选择数组列表的灵活性和优雅性,而不是数组——在大多数情况下,它对程序性能的影响可以忽略不计。
然而,如果你对软件图形渲染或自定义虚拟机进行很少结构变化(没有添加和删除)的频繁迭代,我的顺序访问基准测试表明,数组列表比我的系统上的数组慢1.5倍(在我一岁的iMac上是Java 1.6)。
一些代码:
import java.util.*;
public class ArrayVsArrayList {
static public void main( String[] args ) {
String[] array = new String[300];
ArrayList<String> list = new ArrayList<String>(300);
for (int i=0; i<300; ++i) {
if (Math.random() > 0.5) {
array[i] = "abc";
} else {
array[i] = "xyz";
}
list.add( array[i] );
}
int iterations = 100000000;
long start_ms;
int sum;
start_ms = System.currentTimeMillis();
sum = 0;
for (int i=0; i<iterations; ++i) {
for (int j=0; j<300; ++j) sum += array[j].length();
}
System.out.println( (System.currentTimeMillis() - start_ms) + " ms (array)" );
// Prints ~13,500 ms on my system
start_ms = System.currentTimeMillis();
sum = 0;
for (int i=0; i<iterations; ++i) {
for (int j=0; j<300; ++j) sum += list.get(j).length();
}
System.out.println( (System.currentTimeMillis() - start_ms) + " ms (ArrayList)" );
// Prints ~20,800 ms on my system - about 1.5x slower than direct array access
}
}
这取决于你如何访问它。
存储后,如果你主要想做搜索操作,很少或不需要插入/删除,那么就去数组(因为在数组中搜索是在O(1)中完成的,而添加/删除可能需要重新排序元素)。
存储之后,如果你的主要目的是添加/删除字符串,很少或没有搜索操作,那么就去List。