原本认为数组一种简单的数据结构,但是看到后来才发现,很多的数据结构最终的实现都是由数组实现的。
数组的局限性分析:
①、插入快,对于无序数组,即元素没有按照从大到小或者某个特定的顺序排列,只是按照插入的顺序排列。无序数组增加一个元素很简单,只需要在数组末尾添加元素即可,但是有序数组却不一定了,它需要在指定的位置插入。
②、查找慢,当然如果根据下标来查找是很快的。但是通常我们都是根据元素值来查找,给定一个元素值,对于无序数组,我们需要从数组第一个元素开始遍历,知道找到那个元素。有序数组通过特定的算法查找的速度会比无需数组快,后面我们会讲各种排序算法。
③、删除慢,根据元素值删除,我们要先找到该元素所处的位置,然后将元素后面的值整体向前面移动一个位置。也需要比较多的时间。
④、数组一旦创建后,大小就固定了,不能动态扩展数组的元素个数。如果初始化你给一个很大的数组大小,那会白白浪费内存空间,如果给小了,后面数据个数增加了又添加不进去了。
很显然,数组虽然插入快,但是查找和删除都比较慢,所以我们不会用数组来存储所有的数据,那有没有什么数据结构插入、查找、删除都很快,而且还能动态扩展存储个数大小呢,答案是有的,但是这是建立在很复杂的算法基础上,后面我们也会详细讲解。
数组的初始化
java语言是典型的静态语言,因此java的数组是静态的,即当数组被初始化之后,该数组的长度时不可变的,Java程序中的数组必须经过初始化才可使用。所谓初始化,就是为数组对象的元素分配内存空间,并为每个数组元素制定初始值。
public class ArrayTest { public ArrayTest() { String[] books=new String[]{"android","java","c","c++"}; String[] country=new String[]{"中国","美国","俄罗斯"}; String[] name=new String[5];//采用动态初始化的语法初始化 } }
public class ArrayTest { public ArrayTest() { String[] books=new String[]{"android","java","c","c++"}; String[] country=new String[]{"中国","美国","俄罗斯"}; String[] name=new String[5];//采用动态初始化的语法初始化 //让books的数组变量,country的数组变量指向name所引用的数组 books=name; country=name; books[2]="小明"; } }
此时books,country和name数组变量实际上引用同一个数组对象,因此,当访问books数组,country数组的长度时,将看到输出5,因此books[2]="小明",name数组的第二个元素的值也会随之改变。
Java数组扩容的原理
1)Java数组对象的大小是固定不变的,数组对象是不可扩容的。
2)利用数组复制方法可以变通的实现数组扩容。
3)System.arraycopy()可以复制数组。
4)Arrays.copyOf()可以简便的创建数组副本。
5)创建数组副本的同时将数组长度增加就变通的实现了数组的扩容。
public class Arrays {
/** * Copies the specified array, truncating or padding with nulls (if necessary) * so the copy has the specified length. For all indices that are * valid in both the original array and the copy, the two arrays will * contain identical values. For any indices that are valid in the * copy but not the original, the copy will contain <tt>null</tt>. * Such indices will exist if and only if the specified length * is greater than that of the original array. * The resulting array is of the class <tt>newType</tt>. * * @param <U> the class of the objects in the original array * @param <T> the class of the objects in the returned array * @param original the array to be copied * @param newLength the length of the copy to be returned * @param newType the class of the copy to be returned * @return a copy of the original array, truncated or padded with nulls * to obtain the specified length * @throws NegativeArraySizeException if <tt>newLength</tt> is negative * @throws NullPointerException if <tt>original</tt> is null * @throws ArrayStoreException if an element copied from * <tt>original</tt> is not of a runtime type that can be stored in * an array of class <tt>newType</tt> * @since 1.6 */ public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) { @SuppressWarnings("unchecked") T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength); System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } /** * Copies the specified array, truncating or padding with zeros (if necessary) * so the copy has the specified length. For all indices that are * valid in both the original array and the copy, the two arrays will * contain identical values. For any indices that are valid in the * copy but not the original, the copy will contain <tt>(byte)0</tt>. * Such indices will exist if and only if the specified length * is greater than that of the original array. * * @param original the array to be copied * @param newLength the length of the copy to be returned * @return a copy of the original array, truncated or padded with zeros * to obtain the specified length * @throws NegativeArraySizeException if <tt>newLength</tt> is negative * @throws NullPointerException if <tt>original</tt> is null * @since 1.6 */ public static byte[] copyOf(byte[] original, int newLength) { byte[] copy = new byte[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
}
public final class System {
/** * The byte[] specialized version of arraycopy(). * * @hide internal use only */ public static void arraycopy(byte[] src, int srcPos, byte[] dst, int dstPos, int length) { if (src == null) { throw new NullPointerException("src == null"); } if (dst == null) { throw new NullPointerException("dst == null"); } if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > src.length - length || dstPos > dst.length - length) { throw new ArrayIndexOutOfBoundsException( "src.length=" + src.length + " srcPos=" + srcPos + " dst.length=" + dst.length + " dstPos=" + dstPos + " length=" + length); } if (length <= ARRAYCOPY_SHORT_BYTE_ARRAY_THRESHOLD) { // Copy byte by byte for shorter arrays. if (src == dst && srcPos < dstPos && dstPos < srcPos + length) { // Copy backward (to avoid overwriting elements before // they are copied in case of an overlap on the same // array.) for (int i = length - 1; i >= 0; --i) { dst[dstPos + i] = src[srcPos + i]; } } else { // Copy forward. for (int i = 0; i < length; ++i) { dst[dstPos + i] = src[srcPos + i]; } } } else { // Call the native version for longer arrays. arraycopyByteUnchecked(src, srcPos, dst, dstPos, length); } }
}