数组
我们为什么会用到数组呢?Java中为啥会定义数组呢?在Java中变量的定义是数据类型 变量名 = 初始值。那么我们要是定义10个整型的变量呢?定义100个整型的变量呢?我们一个一个定义岂不是很麻烦而且很慢?所以引出了数组。
数组的定义
数组是用来盛放同种数据类型的集合,在内存中是一个连续的空间。
数组的创建
数组的创建
方式一:
数据类型 [] 数组名 = new 数据类型[N](和前面的一致);
N是用来存放数组长度的
方式二:
数据类型 数组名[] = {元素};//这种不建议使用,和C语言中的一样。int []这样定义更清晰
数组的初始化
数组的初始化分为动态初始化和静态初始化。
//静态初始化
int [] arr = new int[] {1,2,3};
但我们编写的时候一般省略new int[]
int [] arr = {1,2,3};虽然省略了new int[]但是编译的时候,计算机会自己加上,这样只是方便了我们编写代码。
//动态初始化
int [] array = new int[10];
这里我来说几个注意点:
- 在上面的静态初始化时,可以不用在后面的new int[]中指定长度,因为计算机会根据{}中的元素来确定长度。
- 静态初始化的时候,{}中的数据类型必须与前面的一致。
- 对于静态初始化我们有两种方式,上面也提到过了,这里需要注意,完整写法的可以拆分写,简写方式的不可以。
int [] arr = new int[]{1,2,3,4};//这样的时候可以拆开来写
int [] arr;
arr = new int[]{1,2,3,4};
//简写的时候不可以拆开来写
int [] arr = {1,2,3,4};
int [] arr;
arr = {1,2,3,4};//这样拆开写会编译错误
- 对于动态初始化时,后面标明了元素的个数:10。数组中下标是从0开始的,所以10个元素下标是0-9.
- 对于没有初始化的数组,系统会自动分配默认值,动态分配时,创建了10个int类型的元素,但并没有赋值,此时系统会分配默认值0。下图为数组在内存中存储的情况和对于基本数据类型的默认值。
对于引用类型的默认值是null。(null 在 Java 中表示 “空引用” , 也就是一个不指向对象的引用。Java中null并不是就是等于0)
- 对于动态分配时也可以拆开编写。
int [] arr = new int[10];和下面拆开后一样。
int [] arr;
arr = new int [10];
数组的使用
数组最常用到的就是遍历和访问元素。
- 访问元素
数组中的元素下标为[0,N),比方说有10个元素,下标能取到的就是0-9。由于数组在内存中的地址是连续的,所以访问具有随机性。通过数组名[下标]来访问。 - 遍历元素
元素的遍历可以理解为三种方式,这里也需要知道一个知识点,对于数组的长度,我们可以使用数组名.length来求得。
//遍历数组
int [] arr = new int[] {1,2,3,4,5,6,7,8,9};
for(int i = 0; i < 9; i++) {
System.out.print(arr[i] + "\t");
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
for (int x:arr) {
System.out.print(x + "\t");
}
第一种的长度为我们自己数出来的,但如果元素很多,我们再一个一个数就很不现实,所以用到更多的为第二种方法,使用length求得数组的长度。
方法三为for-each方法遍历数组,这里用到的不是数组下标遍历,而是访问数组的元素,for(int x:arr),定义一个变量和数组元素同类型,然后去访问数组内的元素。
JVM内存分布
在最初,我就直接告诉你们了,对象存在堆上,局部变量存在栈上,那么其余的呢?内存到底怎么分布的呢?
再谈基础数据类型和引用类型
根据上述画的图我猜大家也对内存有了了解,而且对于基本数据类型和引用类型的区别也有了大致了解。
基本数据类型存储的为值
引用数据类型存储的为地址。
数组练习
在我上一篇文章中,也有数组的使用,也是个易考点,详细可以看看上一篇的那一块。数组的形参实参
java.util.Arrays这个包中包含了很多操作数组的方法,我们可以自己编写方法也可以使用Arrays自带的
数组的拷贝
//数组拷贝
//自己编写的拷贝
int[] arr = {1,2,3,4};
int[] array = arr;
//Arrays中的拷贝
int[] array1 = Arrays.copyOf(arr,arr.length);
//范围拷贝
int[] array2 = Arrays.copyOfRange(arr,2,3);//范围拷贝,[2,3)
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array1));
System.out.println(Arrays.toString(array2));
自己编写的拷贝和Arrays中自带的拷贝有啥区别呢?来看图吧!
输出数组
上面我们也用到了,输出数组我们可以遍历输出,我们也可以用Arrays中的方法
Arrays.toString(数组名)-----将数组转为字符串输出
输出数组中元素平均值
int[] array = {1,2,3,4};
int sum = 0;
double avg = 0;
for (int x:array) {
sum += x;
}
avg = sum / (double)array.length;
System.out.println(avg);
顺序查找指定元素
//顺序查找指定元素
int[] arr = {1,8,9,3,7,59,6};
int count = 0;
for(int x : arr) {
if (x == 59) {
System.out.println("下标是:" + count);
System.out.println("找到了");
}else {
count++;
continue;
}
}
二分查找
这个只可用于有序数组。
//二分查找,只可以用于有序的数组
int[] arr = {14,15,36,49,59,88};
int num = 59;
int mid = arr.length / 2;
int left = 0;
int right = arr.length - 1;
while (left <= right) {
if (arr[mid] == num) {
System.out.println(mid);
System.out.println("找到了");
break;
}else if (arr[mid] > num) {
right = mid - 1;
mid = (left + right) / 2;
}else {
left = mid + 1;
mid = (left + right) / 2;
}
}
冒泡排序
我写的这个冒泡并不是最快的,还有很多优化方法,大家可以发在评论区。
//冒泡排序
int[] arr = {15,96,55,3,1,58};
int temp = 0;
//趟数
for (int i = 0; i < arr.length - 1; i++) {
//每趟比较的次数
for (int j = 0; j < arr.length - 1; j++) {
if (arr[j] < arr[j + 1]) {
continue;
}else {
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
数组逆序
//数组逆序
int[] arr = {12,59,86,1,58,33};
int left = 0;
int right = arr.length - 1;
int temp = 0;
while (left < right) {
temp = arr[right];
arr[right] = arr[left];
arr[left] = temp;
left++;
right--;
}
System.out.println(Arrays.toString(arr));
二维数组
二维数组本质上也是一维数组。
二维数组的定义为
数据类型[][] 变量名 = new 数据类型[行数][列数]{初始化数据};
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};也可以这样初始化
二维数组的行数和列数可以不同。列数可以省略,但是行数不可以省略。
三维思维数组同理,大家自己试着画画内存图吧!