数组的定义:
之前在定义数据的时候,大部分都是用变量来存储数据
如果我们的程序中出现大量的数据怎么办?
连续输入多个数字,连续输入多个坐标点,一般而言会创建多个变量存储这些数据,显得比较麻烦。
这些变量基本上类型是共通的,那我们就可以用一个容器将所有的数字进行管理。类似于字符串,字符串其实就是若干个字符的容器而已,“abc”可以通过索引/角标来获取其中某一个字符。[1,2,3,4,5]类似字符串能够也可以通过索引/角标来获取其中某一个数字呢?那么这个容器我们称之为数组。数组就是一系列空间大小相等且地址连续的一片存储空间。
数组主要解决多变量多数据的存储问题,方便程序后期统一维护操作数据
为什么空间大小是相等的呢?就是为了方便统一维护我们的数据,必须得保证数据之间的类型是一样的。
为什么变量空间的地址是连续的呢?就是为了方便统一操作我们的数据
但凡在堆内存中创建的对象都会有默认初始值
几种常见的数组创建方式:
1、元素类型 [] 数组名 = new 元素类型[数组的长度] 如: int [] array = new int[5];
2、元素类型 数组名[] = new 元素类型[数组长度] 如: int array[] = new int [6];
3、元素类型 [] 数组名 = new 元素类型[]{元素,元素,元素…} 如: int [] array = new int [] {1,2,3,4,5,6,7};
4、元素类型 [] 数组名 = {}; 如: int [] array = {1,2,3,4,5,6,7}
数组的内存分配及特点
内存结构
Java程序在运行时,需要在内存中的分配空间。为了提高运算效率,有对空 间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈内存
用于存储局部变量,当数据使用完,所占空间会自动释放。
堆内存
数组和对象,通过new建立的实例都存放在堆内存中。
每一个实体都有内存地址值
实体中的变量都有默认初始化值
int——>0
double——>0.0
boolean——>false
char——>'\u0000' 空字符ASCII表
方法区
本地方法区:调用的是Windows系统底层资源
寄存器:和CPU有关
数组操作问题
1、数组脚标越界异常(ArrayIndexOutOfBoundsException)
class A
{
public static void main(String[] args)
{
int [] array = new int[3];
System.out.println(array[3]);
/*由于访问了不存在的角标,
所以会出现异常
*/
}
}
2、空指针异常(NullPointerException)
class A
{
public static void main(String[] args)
{
int [] array =null;
System.out.println(array[0]);
/*由于array=null,所以array并没有指向实体,而却在操作实体中的元素
所以会出现异常*/
}
}
数组的基本操作
数组遍历
遍历数组就是获取数组中的每个元素,通常遍历数组使用for循环
class A
{
//实现数组遍历
public static void main(String[] args)
{
int [] array = {1,4,6,4,8,9,11,56};
for(int i=0;i<array.length;i++){
System.out.println(array[i]);
}
}
}
数组获取最值
class A
{
//获取数组中的最大值
public static void main(String[] args)
{
int [] array = {1,4,6,4,8,9,11,56};
/*第一种方式:定义第三方变量,初始化为array[0],
让这个变量与数组中的元素进行比较,并记录较大的值
*/
int temp = array[0];
for(int i=1;i<array.length;i++){ //对数组进行遍历,并从下标1开始
//取出较大的值
if(array[i]>temp)
temp = array[i];
}
System.out.println("数组array中的最大值是:"+temp);
//第二种方式:定义第三方变量,初始化值为0,作为数组的下标使用
int index = 0;
for(int i=1;i<array.length;i++){
if(array[i]>array[index])
index = i;
}
System.out.println("数组array中的最大值是:"+array[index]);
}
}
数组的赋值
class A {
public static void main(String[] args) {
int intArray [] = new int []{2,3,4,5,3}; // 声明并静态初始化
String strArray [] ; //声明String类型的数组
strArray = new String [] {}; //静态初始化,这种方式没有指定初始值
String strArray1 [] ;
strArray1 = new String []{"asdfkla","asdfawe","asd","we24e","sdw234"};
System.out.println(strArray1.length);
数组的查找
线性查找:也就是按顺序一位一位的查找,找到要查找数的索引(下标)。
弊端:数据量大的时候,在最差的情况下,计算机的负载也非常的大,效率低。
public static void main(String[] args) {
System.out.println("请输入要查找的数");
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
int[] arr = {2,4,6,8,10,12,14,16};
int index = find(arr,num);
if (index == -1){
System.out.println("找不到该数");
}else {
System.out.println("查找到的该数的下标为" + index);
}
}
public static int find(int[] arr,int num){
for (int i = 0;i<arr.length;i++){
if (arr[i] == num) {
return i;
}
}
return -1;
}
二分查找
优化了查找的效率
弊端:数组必须经过排序。
public class A {
public static void main(String[] args) {
//目标数组
int[] arr = new int[] {1,2,3,4,5,6,7,8,9};
//目标元素
int target = 8;
//记录开始位置
int begin = 0;
//记录结束位置
int end = arr.length;
//记录中间的位置
int mid = (begin + end)/2;
//记录目标位置
int index = -1;
//循环查找
while(true) {
//判断中间的这个元素是不是要查找的元素
if(arr[mid] == target) {
index = mid;
break;
//如果中间这个元素不是要查找的元素
}else {
//判断中间这个元素是不是比目标原属大
if(arr[mid]>target) {
//把结束位置调整到中间位子的前一个位置
end = mid - 1;
//中间元素比目标元素要小
}else {
//把结束位置调整到中间位子的后一个位置
begin = mid + 1;
}
//取出新的中间的位置
mid = (begin+end)/2;
}
}
System.out.println(index);
}
}