文章目录
java之数组
数组的概述
- 数组是存储多个变量(元素)的东西(容器)
- 这多个变量的数据类型要要一致
数组:存储同一种数据类型的多个元素容器
数组定义格式
A:数据类型[] 数组名;
B:数据类型数组名[];
举例:
int[]arr; 定义了一个int类型的数组,数组名是arr
int arr[] ;定义了一个int类型的变量,变量名是arr数组
//不推荐
错误的声明数组的方式,声明数组的时候不能指定其大小
int [5] intErrorArray0;
int intErrorArray1[5];
数组初始化
java中数组必须先初始化,然后才能使用。
所谓初始话,就是为了数组中的数组元素分配内存空间。并为每个数组元素赋值。
数组的初始化方式
动态初始化
动态初始化:初始化时只指定数组长度,又系统为数组分配初始值。
格式: 数据类型[]数组名 = new 数据类型[数组长度]
举例:
int[]arr = new int[3];
左边:
\* int:说明数组中的元素的数据类型是int类型
\* []:说明这是一个数组
\* arr:是数组的名称
右边:
\* new:为数组分配内存空间
\* int:说明数组中的元素的数据类型是int类型
\* 3:数组的长度,其实就是数组中的元素个数
\* []:说明这是一个数组
注意:一旦创建了数组,就不能在改变它的长度(不过,当然可以改变单个的数组元素)。如果程序运行中需要经常扩展数组的大小,就应该使用另一种数据结构——数组列表(array list)
静态初始化
静态初始化;初始化时指定每个数组元素的初始值,由系统决定数组长度
例如:
int[] smallPrimes = {2,3,5,7,11,13};
最后一个值后面允许有逗号,如果你要不断为数组增加值,这回很方便。
还可以声明一个匿名数组:
new int [] {17,19,23,29,31,37}
这会分配一个新数组并填入括号中提供的值,它会统计初始值的个数,并相应地设置数组大小。可以使用这种语法重新初始化一个数组而无须创建变量。例如:
array = new int[] {1, 2, 5, 89};
这个语句是下面语句的简写:
int[] tempArray = {1, 2, 5, 89};
array = tempArray;
注意:在Java中允许数组长度为0。在我们要编写一个结果为数组的方式时,如果碰巧结果为空,那么这种语法形式显得特别有用。此时可以创建一个长度为0的数组:值得注意的是:数组长度为0和null是不一样的,这个需要特别注意。null代表这个数组并不存在,长度为0表示这个数组不包含任何元素,但是数组是存在的。
访问数组元素
创建一个数字数组时,所有元素都初始化为0。
boolean数组的元素会初始化为false。
对象数组的元素则初始化为一个特殊值null,表示这些元素还未存放任何对象。
注意:访问超过了数组的元素,就会出现“array index out of bounds”异常。
想要获得数组中的元素个数,可以用array.length。
for each 循环
java有一种功能很强的循环结构,可以用来依次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下的值。
格式:
for(循环对象的类型 元素名:对象名){
语句
}
for 循环写法
int[] arr ={1,2,3,4,5};
for(int i = 0; i<arr.length; i++){
System.out.println(arr[i]);
}
for each格式
for(int data :arr){
System.out.println(data);
}
总结:for each循环语句显得更加、更不易出错,因为你不必为了下标的起始值和终止值而操心。如果需要用下标值时或者不想遍历所有元素的时候。
还有一个更加简单的方式打印数组中的所有值,即利用Arrays类的toString方法。调用Arrays.toString(a),返回一个包含数组元素的字符串,这些元素包括在中括号内,并用逗号分隔,例如,“[2,3,5,7,11,13]”。要想打印数组,只需要调用
System.out.print(Arrays.toString(a));
数组拷贝
分别为:for clone() System.arraycopy()Array.copyOf()
要研究数组的拷贝,先看看浅拷贝与深拷贝的概念:
概括起来讲,浅拷贝就是指两个对象公用一个值,一个的改变了另一个也会随之改变,深拷贝则是两个对象虽然值相等,但是相互独立互不影响。
一、For写法
public static void main(String[] args) {
int[] array1 = new int[]{1, 2, 8, 7, 6};
int[] array2 = new int[array1.length];
for (int i = 0;i < array1.length;i++){
array2[i] = array1[i];
}
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
System.out.println("======================");
array2[0] = 100;
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
}
}
输出:
array1 = [1,2,8,7,6]
array1 = [1,2,8,7,6]
====================
array1 = [1,2,8,7,6]
array1 = [100,2,8,7,6]
由结果可以看出,当对复制数组的某个元素进行改变时,并不影响被复制数组对应元素,即对于基本数据类型来说for循环语句是深拷贝。
二、System.arraycopy()写法
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
参数说明:
src:源对象
srcPos:源数组中的起始位置
dest:目标数组对象
destPos:目标数据中的起始位置
length:要拷贝的数组元素的数量
System.arraycopy() 源码如下:
public class ArraycopyTest{
public static void main(String[] args){
char[] c1 = new String("123456").toCharArray();
char[] c2 = new String("abcdef").toCharArray();
System.arraycopy(c1, 2, c2, 1, 2);
System.err.println(Arrays.toString(c1));
System.err.println(Arrays.toString(c2));
}
}
输出:
[1, 2, 3, 4, 5, 6][a, 3, 4, d, e, f]
注意:(1)、System.arraycopy() 在拷贝数组的时候,采用的使用潜拷贝,复制结果是一维的引用变量传递给副本的一维数组,修改副本时,会影响原来的数组。
<font color="red">(2)、如果是数组比较大,那么使用System.arraycopy会比较有优势,因为其使用的是内存复制,省去了大量的数组寻址访问等时间。System.arraycopy()源码,可以看到是native方法:native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。 可以将native方法比作Java程序同C程序的接口。System.arraycopy是不安全的。</font>
三、copyOf写法
从代码可知,数组拷贝时调用的是本地方法 System.arraycopy() ;
Arrays.copyOf()方法返回的数组是新的数组对象,原数组对象仍是原数组对象,不变,该拷贝不会影响原来的数组。copyOf()的第二个自
变量指定要建立的新数组长度,如果新数组的长度超过原数组的长度,则保留数组默认值.
在java中,允许将一个数组变量拷贝到另一个数组变量。这时,两个变量将引用同一个数组
int luckyNumber = smallPrimes;
luckyNumbers[5] = 12;
这样smallPrimes也是12
希望将一个数组的所有值拷贝到一个新的数组中去,就要使用Arrays类的copyOf方法:
int[] copitedLuckNumbers = Arrays.copyOf(luckNumber,luckNumbers.length);
第2个参数时新数组的长度。这个方法通常用来增加数组的大小:
luckNumbers = Arrays.copyOf(luckyNumbers,2 * LuckNumbers.length);
copyOf与System.arraycopy()对比
int[] arr = {1,2,3,4,5};
int[] copied = new int[10];
System.out.println(Arrays.toString(copied));
System.arraycopy(arr, 0, copied, 1, 5);//5是复制的长度
System.out.println(Arrays.toString(copied));
输出:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0][0, 1, 2, 3, 4, 5, 0, 0, 0, 0]
int[] copied = Arrays.copyOf(arr, 10); //10是新数组的长度
System.out.println(Arrays.toString(copied));
copied = Arrays.copyOf(arr, 3);
System.out.println(Arrays.toString(copied));
输出:
[1, 2, 3, 4, 5, 0, 0, 0, 0, 0][1, 2, 3]
区别:Arrays.copyOf() 不只复制数组元素,也创建一个新数组。System.arrayCopy 只复制已有的数组。
四、clone方法
clone方法是从Object类继承过来的,基本数据类型(int ,boolean,char,byte,short,float ,double,long)都可以直接使用clone方法进行克隆,注意String类型是因为其值不可变所以才可以使用。是深拷贝。
int 类型示例
int[] a2 = a1.clone();
a1[0] = 666;
System.out.println(Arrays.toString(a1)); //[666, 3]
System.out.println(Arrays.toString(a2)); //[1, 3]
String类型示例
String[] a2 = a1.clone();
a1[0] = "b1"; //更改a1数组中元素的值
System.out.println(Arrays.toString(a1)); //[b1, a2]
System.out.println(Arrays.toString(a2)); //[a1, a2]
数组排序
对数组进行排序,可以使用Arrays类中的sort方法:
int[] a = new int[10000];
Arrays.sort(a)
这个方法使用了优化的快速排序算法。
多维数组
二维数组(也称为矩阵)储存这些信息。这个数组被称为balance。
初始化:
数据类型[][] [][] 数组名 = new 数据类型[数组长度]行 [数组长度]列
二维数组定义时需要两个中括号,方式如下:
int[][] arr=new int[2][3];
int[][] arr =new int[3][];
定义二维数组arr以后,arr是二维数组,arr[i]是一维数组,arr[i][j]是数据。其中最左边的中括号里面必须有长度
二维数组的遍历
int[][] arr2 = { {1,2},{3,4,5},{6,7,8,9,10} };
int sum2 = 0;
for (int i=0; i<arr2.length; i++) {
for (int j=0; j<arr2[i].length; j++) {
//System.out.println(arr2[i][j])
sum2 += arr2[i][j];
}
}
System.out.println("sum2= "+ sum2);
}
}
二维数组静态初始化与动态初始化的区别:数组范围不同,多占用了很多空间
java虚拟机的内存划分
为了提高效率,就对空间进行了不同区域的划分,因为每一篇区域都有特定的处理数据方式和内存管理方式
寄存器:给CPU用,与开发无关
本地方法栈:JVM在使用操作系统功能的时候用,和我们开法无关
方法区:存储可以运行的class文件
堆内存:存储对象或者数组,new来创建的,都存储在堆内存
方法栈:方法运行时使用内存,比mian方法运行,进入方法栈中执行。
程序执行流程:
1、main方法进入方法栈执行
2、创建数组,jvm会在堆内存中开辟空间,存储数组
3、数组在内存中会有自己的内存地址,以十六进制数表示
4、数组中有三个元素,默认值0
5、JVM将数组的内存地址赋值给引用类型变量arr
6、变量arr保存的是内存数组中的地址,而不是一个具体数值,因因此被称为引用数据类型
java常用API
Java常用API
输出数组 Arrays.toString()
int[] array = { 1, 2, 3 };
System.out.println(Arrays.toString(array));
数组转List Arrays.asList()
String[] array2 = {"a", "b", "c", "d"};
System.out.println(array2); // [Ljava.lang.String;@13b6d03
List list = new ArrayList(Arrays.asList(array2));
System.out.println(list); // [a, b, c, d]
list.add("GG");
System.out.println(list); // [a, b, c, d, GG]
数组转Set Arrays.asList()
String[] array = { "a", "b", "c", "d", "e" };
Set set = new HashSet(Arrays.asList(array));
System.out.println(set);
List转数组 toArray()
List list = new ArrayList();
list.add("a");
list.add("b");
list.add("c");
String[] array = new String[list.size()];
list.toArray(array);
for (String s : array)
System.out.println(s);
数组中是否包含某个值
String[] array = { "a", "b", "c", "d", "e" };
boolean isEle = Arrays.asList(array).contains("a");
System.out.println(isEle);
数组复制
int array[] = new int[] { 1, 2, 3, 4 };
int array1[] = new int[array.length];
System.arraycopy(array, 0, array1, 0, array.length);
数组合并
int[] array1 = { 1, 2, 3, 4, 5 };
int[] array2 = { 6, 7, 8, 9, 10 };
int[] array = org.apache.commons.lang.ArrayUtils.addAll(array1, array2);
System.out.println(Arrays.toString(array));
String数组转字符串(使用指定字符拼接)
String[] array = { "a", "b", "c" };
String str = org.apache.commons.lang.StringUtils.join(array, ", ");
System.out.println(str);
数组逆序
int[] array = { 1, 2, 3, 4, 5 };
org.apache.commons.lang.ArrayUtils.reverse(array);
System.out.println(Arrays.toString(array));
数组元素移除
int[] array = { 1, 2, 3, 4, 5 };
int[] removed = org.apache.commons.lang.ArrayUtils.removeElement(array, 3);
System.out.println(Arrays.toString(removed));