数组(Array)
数组
数组的概述&数组的内存分析
之前我们在定义数据的时候,基本上都是用变量来存储数据。但是如果我们的程序中出现大量的数据该怎么办?比如连续输入多个数字,连续输入多个坐标点,对于这种一般而言计算机会创建多个变量来存储这些数据,虽然没有问题,但是显得比较麻烦。我们通过观察可以发现,这些变量基本上类型是共通的,那我们就可以用一个容器将所有的数据进行管理,这类似于字符串,字符串其实就是若干个字符的容器而已,“abc”可以通过索引/角标来获取其中某一个字符,[1,2,3,4,5]类似字符串也能够通过索引/角标来获取其中某一个数字,这个容器我们称之为数组。数组主要解决多变量多数据的存储问题,这方便程序后期统一维护操作数据。
说了这么多关于数组的概述,那么数组的本质到底是什么呢?其实,数组就是一系列空间大小相等且地址连续的一片存储空间。空间大小相等是为了方便统一维护我们的数据,必须得保证数据之间的类型是一样的(多个同类型的变量空间连在一起组成的结构叫数组);至于变量空间地址连续则是为了方便统一操作我们的数据(见下面的数组内存图)。
-
数组的定义&数组的常见错误
数组就是一片地址连续且空间大小一致的存储空间(但是每个空间存的还是其他数据的地址),数组存在于堆内存中,但凡在堆中存储的数据都称之为对象,但凡在堆内存中创建的对象都会有默认初始值,整数类型默认0,浮点类型默认0.0,布尔类型默认false,引用数据类型(对象)默认null。
关于数组的一些注意事项:
1.数组变量存的就是数组在堆内存中首元素的地址;
2.数组提供角标来访问数组当中的元素,数组通过角标来访问元素的具体计算方式是:所要访问数据的地址 = 首元素地址+角标*数据类型大小;
3.数组一旦定义下来,其长度不可改变。数组中有几个地址?就看数组有几个元素空间<==>数组的长度。
数组的创建:
1. 数据类型[ ] 数组名 = new 数据类型[长度] 创建数组只指定长度但不指定内容
2. 数据类型[ ] 数组名 = new 数据类型[ ]{1,2,3,4,5} 创建数组指定内容(指定长度)
3. 数据类型[ ] 数组名 = {1,2,3,4,5} 创建数组指定内容(指定长度)
此外 [ ]表示是一维数组,[ ][ ]表示是二维数组。
来看个例子:
class Test04{
public static void main(String[] args){
//1.创建长度为5的String型数组
String[] strArr = new String[5];
//访问strArr数组中第1个元素
System.out.println(strArr[0]);
//2.创建长度为5的int型数组
int[] arr = new int[5];
//访问arr数组中第4个元素
System.out.println(arr[3]);
//这个输出语句是访问arr中第11个元素,但因为arr数组的长度只有5,
//所以会出错。错误是"ArrayIndexOutOfBoundsException角标越界"
//System.out.println(arr[10]);
//新创建一个变量arr2指向原来的数组,此时数组还是
//那个数组对象,只不过有两个变量引用到了而已。
int[] arr2 = arr;
arr2[0] = 10;
System.out.println(arr[0]);//10
arr2 = null;
//System.out.println(arr2[0]);arr2为空,所以出错NullPointerException空指针异常
arr = null;
//此时此刻,数组对象没有任何变量引用它
//数组对象在堆内存中就没有存在的意义了
//所以该对象变成垃圾,由【垃圾回收器gc】处理
//【垃圾回收器】是JVM中的一个程序,专门用于负责处理堆内存中垃圾数据的。
//垃圾的处理并不是及时的,由【gc】来控制,当垃圾堆攒到一定程度时由【gc】来处理
//特殊的在C/C++中,如果出现对象垃圾,必须程序员手动处理,借助free()及时处理
}
}
如上述代码所述,数组中常见的错误有两种,一个是"ArrayIndexOutOfBoundsException角标越界",一个是"NullPointerException空指针异常",所以我们写代码的时候要特别注意不要发生这两种错误。另外,当把一个数组变为null后,此时也就没有任何变量去引用它,数组对象在内存中也没有存在意义,所以会被垃圾回收器回收。
-
基本数组操作
一般有求最大值、最小值,对数组进行遍历,对数组进行赋值等,具体都写在代码中了。
import java.util.*;
class Test05{
public static void main(String[] args){
//求最大值、最小值操作
maxormin();
//赋值操作
fuzhi();
//遍历操作
bianli();
}
//求最大值、最小值操作
public static void maxormin(){
//计算最大值
//计算最小值的角标
//获取最大的值10,获取最小值的角标4
int[] arr={10,2,8,3,1,6,4,7,9,5};
int max=arr[0];
int min_index=0;
for(int i=0;i<arr.length;i++){
if(arr[i]>max){
max=arr[i];
}
if(arr[i]<arr[min_index]){
min_index=i;
}
}
System.out.println("最大值"+max);//最大值10
System.out.println("最小值角标"+min_index);//最小值角标4
}
//赋值操作
public static void fuzhi(){
Scanner scanner = new Scanner(System.in);
//System.out.print("请输入10个数字:");
int[] arr2 = new int[10];
for(int i=0;i<arr2.length;i++){
System.out.print("请输入1个数字:");
arr2[i] = scanner.nextInt();
}
for(int i=0;i<arr2.length;i++){
System.out.print(arr2[i]+" ");
}
}
//遍历操作
public static void bianli(){
int[] arr={1,2,3,4,5,6,7,8,9};//[0,8]
//数组只有一个唯一的属性length,数组的长度
System.out.println(arr.length);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
-
查找操作
查找操作这里就说一下二分查找和线性查找,具体操作都写在代码中了。
class Test06{
public static void main(String[] args){
//线性查找
linearSearch();
//二分查找
binarySearch();
}
public static void binarySearch(){
//二分查找有个前提,数组必须有序
/*
最好情况 查46 1次就出来了
最坏情况 查12/60 O(logn)
*/
int[] arr = {12,17,21,32,38,41,46,49,50,50,51,59,60};
int key = 46;
int index = -1;
int min_index = 0;
int max_index = arr.length - 1;
int mid_index = (min_index + max_index) / 2;
while(arr[mid_index]!=key){
if(key < arr[mid_index]){
max_index = mid_index-1;
}
if(arr[mid_index] < key){
min_index = mid_index+1;
}
if(min_index > max_index){
index = -1;
break;
}
mid_index = (min_index + max_index) / 2;
}
System.out.println(mid_index);
}
public static void linearSearch(){
/*
最好情况 查10 1次就出来了
最坏情况 查5 10次才出来
当数组的长度越大的话,最坏情况越差
时间复杂度(最坏情况)为O(n),是线性阶
*/
int[] arr={10,2,8,3,1,6,4,7,9,5};
int key=11;
int index=-1;//key元素不存在
for(int i=0;i<arr.length;i++){
if(arr[i]==key){
index=i;
break;
}
}
System.out.println(index);
}
}
未完待续........
上一篇: socket超时设置
下一篇: 记录:google map加载服务