一、数组的定义及初始化
静态定义:
String[] bArray = {"a","b","c", "d", "e"};
String[] cArray = new String[]{"a","b","c","d","e"};
动态定义:
String[] aArray = new String[5];
二、数组的存储(同对象一样)Java中的数组存储两类事物: 基本类型(int,char,...),或者引用(对象指针).
当一个对象通过 new 创建,那么将在堆内存中分配一段空间,并且返回其引用(指针).
对于数组,也是同样的方式.
1. 一维数组
int[] arr 指向 包含3个整数的数组. 假设创建的是包含10个整数的数组,也是同样的用法 —— 分配指定大小的内存,并返回数组的引用。
- int arr[] = new int[3];
2. 二维数组
二维数组又有什么区别呢?实际上,在Java中只有一维数组。二维数组本质上也是一维数组,只是数组中的每一个元素都指向了另一个一维数组而已。
- int[ ][ ] arr = new int[3][ ];
- arr[0] = new int[3];
- arr[1] = new int[5];
- arr[2] = new int[4];
同样的原理,多维数组也是如此.
3. 数组分配在内存的哪个区域?
Java中的数组,也是对象(继承Object),因此数组所在的区域和对象是一样的.
我们知道,JVM 运行时数据区
包括 JVM栈,堆内存,以及其他区域. 看下面的关于对象的简单示例,我们一起来了解数组如何分配,以及引用保存在哪里.
- class A {
- int x;
- int y;
- }
- ...
- public void m1() {
- int i = 0;
- m2();
- }
- public void m2() {
- A a = new A();
- }
- ...
上面的代码片段中,让我们执行 m1()方法看看发生了什么:
- 当 m1 被调用时,一个新的栈帧(Frame-1)被压入JVM栈中,当然,相关的局部变量也在 Frame-1中创建,比如 i;
- 然后 m1调用m2,,又有一个新的栈帧(Frame-2)被压入到JVM栈中; m2方法在堆内存中创建了A类的一个对象,此对象的引用保存在 Frame-2的局部变量 a 中. 此时,堆内存和栈内存看起来如下所示:
而 数组(Array)被当做Object处理,因此数组如何保存的,你应该明白了.
所有局部变量放在栈内存当中,(不管其是基本类型的变量还是引用类型的变量),但引用类型变量所引用的对象(包括数组、普通java对象)则总是存储在堆内存中。
java语言不允许直接访问堆内存中的数据,因此无法直接访问堆内存中的数组对象,程序将通过数组引用变量来访问数组。
在定义局部变量时:
基本类型产生了一个值存放在栈中,变量的值就是栈的地址处的值。
引用类型则产生了一个对象,存放在内存堆中,同时将内存堆对象的指针地址(引用地址)存放在了栈中,变量的值实际是栈中的引用地址。
关于数组在内存中的分布,首先,一定是在堆中申请了一段连续的内存,内存的占用要看数组的类型,如果是基本类型,如int,则按照每个元素4个字节方式存放,例如int[] x = new int[4]; 这个时候就产生了1个对象,4个元素,每个元素占4个字节,数组对象头还要占一些字节(应该是12个)。同时,返回堆中的数组对象首地址给栈中的变量。对于引用类型,数组中的元素要存放数组的引用指针,一般也是4个字节来表示一个元素,即使这个数组的引用为null,一样要为其保留4个字节的内存空间。
java的数组是一种引用型的变量,数组变量并不是数组本身。他只是指向堆内存中的数组对象。
对数组变量来说,他们并不需要进行所谓的初始化,只要让数组变量指向一个有效的数组对象,程序即可正常使用该数组变量。需要初始化的永远只是该引用变量所引用的对象,而不是引用变量本身。对基本类型数组而言,数组元素的值直接存储在对应的数组元素上。因此基本类型数组的初始化比较简单:程序直接先为数组分配内存空间,再将数组元素的值存入对应的内存中。引用类型数组的初始化引用类型数组的数组元素依然是引用类型的,因此数组元素里存储的还是引用。他指向另一块内存,这块内存里存储了该变量所引用的对象(包括数组和java对象)。对于引用类型的数组而言,他的数组元素其实是一个引用类型的变量,因此可以指向任何有效的内存——此处”有效“的意思是指强类型的约束。比如Person[]类型的数组,它的每个数组元素都相当于Person类型的变量,因此他的数组元素只能指向Person对象。String[] names = { "Michael", "Orson", "Andrew" }; // 动态初始化数组 String[] animal = new String[4]; // 让animal 指向 namens 数组所引用的数组 names = animal;
问题:引用变量何时只是栈内存中的变量本身,何时又变为引用实际的java对象?答:其实规则很简单,引用变量本质上只是一个指针,只要程序通过引用变量访问属性或方法,该引用变量将会由他所引用的对象代替。
三、将数组变成字符串(Arrays类toString)
int[] intArray = { 1, 2, 3, 4, 5 }; String intArrayString = Arrays.toString(intArray); System.out.println(intArrayString); // [1, 2, 3, 4, 5]四、将数组变成ArrayList(Arrays类toString)
int[] intArray = { 1, 2, 3, 4, 5 };
ArrayList<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(intArray));
System.out.println(arrayList);
// [1, 2, 3, 4, 5]
为什么要将Array转换成ArrayList呢?可能是因为ArrayList是动态链表,我们可以更方便地对ArrayList进行增删改,我们并不需要循环Array将每一个元素加入到ArrayList中,用以上的代码即可简单实现转换。
五、将数组变成Set集合(Arrays类toString)String[] stringArray = { "a", "b", "b", "d", "e" };ArrayList<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(intArray));Set<String> set = new HashSet<String>(Arrays.asList(stringArray));System.out.println(set);//[d, e, b, a]六、比较两个数组是否相等(Arrays类equals)Integer[] a1 = { 1, 2, 3, 4, 5 };Integer[] a2 = { 1, 2, 3 };System.out.println(Arrays.equals(a1, a2));//false七、查询数组中是否包含某个值,不循环
String[] stringArray = { "a", "b", "c", "d", "e" }; boolean b = Arrays.asList(stringArray).contains("a"); System.out.println(b); // true先使用Arrays.asList()将Array转换成List<String>,这样就可以用动态链表的contains函数来判断元素是否包含在链表中。八、连接两个数组(ArrayUtils类addAll)
int[] intArray = { 1, 2, 3, 4, 5 }; int[] intArray2 = { 6, 7, 8, 9, 10 }; // Apache Commons Lang library int[] combinedIntArray = ArrayUtils.addAll(intArray, intArray2);ArrayUtils是Apache提供的数组处理类库,其addAll方法可以很方便地将两个数组连接成一个数组。
九、
将数组中的元素以字符串的形式输出
(
StringUtils
类join)
String j = StringUtils.join(new String[] { "a", "b", "c" }, ", "); System.out.println(j); // a, b, c同样利用StringUtils中的join方法,可以将数组中的元素以一个字符串的形式输出。
十、数组翻转(ArrayUtils类reverse)int[] intArray = { 1, 2, 3, 4, 5 }; ArrayUtils.reverse(intArray); System.out.println(Arrays.toString(intArray)); //[5, 4, 3, 2, 1]参考 http://www.codeceo.com/article/10-java-array-method.html十一、从数组中移除一个元素(ArrayUtils类reverse)int[] intArray = { 1, 2, 3, 4, 5 }; int[] removed = ArrayUtils.removeElement(intArray, 3);//create a new array System.out.println(Arrays.toString(removed));十二、数组排序(Arrays类sort)
Arrays
类可以实现数组的排序,不管数组的元素是引用类型还是值类型。 下面的代码实现数组的正序、倒序排序:
String[] stringArray = { "a", "c", "b", "d", "e" };
Arrays.sort(stringArray);
for (String i : stringArray) {
System.out.print(i);
}
// abcde
Arrays.sort(stringArray, Collections.reverseOrder());
for (String i : stringArray) {
System.out.print(i);
}
// edcba
十三、数组拷贝copyOf
//[e, d, c, b, a, null]