03_数组
数组:
一、数组的常见概念:
存储数据——变量 : 每一个变量 只能存储一种类型的一个数据( int i = 10;)
数组:可以存储同种类型的多个数据
一维数组 二维数组 多维数组(不使用)
·数组名
·下标(或索引)
·元素
·数组的长度
数组:引用类型
数组的分类:
1.按照维度:
一维数组、二维数组、三维数组、…
2.按照元素的数据类型分:
基本数据类型元素的数组、引用数据类型元素的数组(即对 象数组)
二、一维数组的使用:
1.一维数组的声明方式:
声明:type var[ ](.net的常用形式) 或 type[ ] var(Java的常用形式)——例如:(int [ ]arr);
Java语言中声明数组时不能指定其长度(数组中元素的数), 例如: int a[5]; //非法
2.一维数组的初始化:
(1)动态初始化:数组声明且为数组元素分配空间与赋值的操作分开进行
int[] arr = new int[10]; arr[0] = 值
public static void main(String[] args) {
//动态初始化 在声明数组的时候 指定数组的长度 而不指定数组的元素
//元素通过后期的动态方式来指定
int[] arr = new int[10];//声明一个长度为10的整型数组
}
(2)静态初始化:在定义数组的同时就为数组元素分配空间并赋值。
1.int[] arr = {元素 元素和元素之间使用 逗号分隔}; int[] arr = new int[] {元素};
2.int[] arr = new int[] {元素};
public static void main(String[] args) {
//静态初始化 声明数组时 不指定数组的长度 直接在其后
//跟上{} 在其中直接列出数组的元素
int[] arr1 = {1,2,3,4,5,6};
//静态初始化的第二种形式
int[] arr2 = new int[] {4,3,2,5,7};
}
3.对于数组元素的引用:
数组元素的引用方式:数组名[数组元素下标](通过角标引用)
arr[0] = 10;//对数组的0号元素赋值
arr[1] = 20;
arr[3] = 11;
// 数组的取值
int a = arr1[0];
int b = arr1[1];
System.out.println(a +"---"+b);
int c = arr[0];
int d = arr[1];
System.out.println(c +"---"+d);
// 在使用数组的时候 需要注意的问题
//arr[10] = 100;//ArrayIndexOutOfBoundsException
int e = arr[9];
System.out.println(e);
// int f = arr[10];
问题:
使用时 不能超出数组的下标的范围
数组存在默认值:
整型(byte short int long)的默认值:0
浮点型(float double):0.0
字符型:空格
boolean:false
数组元素下标从0开始;长度为n的数组合法下标取值范围: 0 —>n-1;如int a[]=new int[3]; 可引用的数组元素为a[0]、a[1]、a[2]
4.数组元素的遍历:
for循环遍历:
for(int i = 开始索引; 索引的范围; 每次的步长){ 可以对数组中的每一个元素进行精确操作;
}
每个数组都有一个属性length指明它的长度,例如:a.length 指明数组a的长度(元素个数) ;
数组一旦初始化,其长度是不可变的
//对数组arr1的遍历
for(int i = 0 ; i < arr1.length;i++) {
System.out.println(arr1[i]);
}
jdk5开始 新增了一种新的遍历方式:
增强for循环 /for…each
写法:for(遍历对象的类型 每次遍历得到的数据保存的变量 :要遍历的对象(数组名称))
例一:
for(int i : arr1) {
// 1 是遍历对象的类型——int 2 每次遍历得到的数据保存的变量——i 3 遍历对象——arr
System.out.println(i);
}
例二:
String[] strArr = new String[] {"aa","bb","cc"};
for(String str : strArr) {
System.out.println(str);
}
增强for和普通for的区别:
//输出数组arr1中的偶数元素
for(int i = 0 ; i < arr1.length;i+=2) {
System.out.println(arr1[i]);
}
增强for无法完成上述需求
增强for适用于对整个数组所有元素的遍历,无法精确控制元素的索引
普通for没有限制,可以精确控制操作对象
增强for中的 i 是临时变量 无法对数组中的元素进行删增改(值传递)
三、数组的常用操作以及方法(重要):
(1)方法:
1.方法:指的是完成特定功能的代码块
代码块就是使用{}括起来一段代码;
2.定义形式:
访问修饰符 ; [static] ; 方法的返回值类型 ; 方法名称;
([形参列表: 参数类型(基本类型/引用类型) 参数名称 多个参数之间使用逗号分隔])
{ 方法所要具体实现的功能的代码; }
例:
public static int getMax(int n){
}
3.方法定义的时候 所定义的形参称为形式参数 简称形参
当使用方法的时候 传入的参数 称为实际参数 简称实参
4.方法的返回值:
有返回值时 确定返回值的类型 可以是基本类型也可以是引用类型
有返回值时 需要在方法体的最后 使用return 语句来返回对应类型的变量或者数据
没有返回值 void
5.形参也分为有和没有(没有就不写,有按照上面写)
6.方法的使用:
方法需要调用才可以执行 除main方法 其他方法都必须调用才能执行 不调用不执行
7.方法的注意事项:
1 main方法是整个程序的入口方法 对于一个javase程 序 始终是从main方法开始执行。
2 main方法的声明形式是固定的。
3 在程序中 所有的方法都是平行。
4 方法的执行:必须在main方法中或者其他方法中调 用:通过方法名称(传入所需参数) 方法如果没有在main 或者其他方法中调用 是不会执行的。
5 方法不能嵌套方法 但是方法可以调用方法
(2)常用操作:
1.求数组中元素的最大、最小数
2.在指定数组中查找特定元素
3. 删除数组中的某一个元素
4.对数组求和
public class ArrayDemo2 {
/**
* 求数组中元素的最大、最小数
* 在指定数组中查找特定元素
* 删除数组中的某一个元素
* 对数组求和
*/
public static void main(String[] args) {
int[] arr1 = new int[] {2,1,5,9,3,4};
int max = getMaxEle(arr1);
System.out.println(max);
//getMaxEle1(arr1);
System.out.println("------------------");
int index = findEleInArr(arr1, 10);
System.out.println(index);
System.out.println("------------------");
boolean f = deleteEle(arr1,5);
System.out.println(f);
print(arr1);
int sum = add(arr1);
System.out.println(sum);
}
// 求数组中的最大值 使用了返回值
public static int getMaxEle(int[] arr) {
int max = arr[0];//假设第一个元素为最大
for(int a : arr) {
if(max < a) {
max = a;
}
}
return max;
}
//没有返回值
public static void getMaxEle1(int[] arr) {
int max = arr[0];//假设第一个元素为最大
for(int a : arr) {
if(max < a) {
max = a;
}
}
System.out.println(max);
}
// 在指定数组中查找特定元素
/*
* 查找元素:找到 没有找到
* 如果找到则返回元素在数组中的索引 如果没有找到 返回-1
*/
public static int findEleInArr(int[] arr , int key) {
int index = -1;
for(int i = 0 ; i < arr.length;i++) {
if(key == arr[i]) {
index = i;
}
}
return index;
}
//删除数组中的某一个元素
public static boolean deleteEle(int[] arr , int target) {
boolean flag = false;
int index = 0;
for(int i = 0 ; i < arr.length;i++) {
if(target == arr[i]) {
index = i;
flag = true;
}
}
for(int i = index ; i < arr.length - 1 ; i++) {
arr[i] = arr[i+1];
}
arr[arr.length- 1] = 0;
return flag;
}
//遍历数组
public static void print(int[] arr) {
for(int a : arr) {
System.out.println(a);
}
}
public static int add(int[] arr) {
int sum = 0 ;
for(int a : arr) {
sum += a;
}
return sum;
}
}
四、数据在计算机中是如何存储的
基本类型数据和引用类型数据存储的区别:
(1)JVM:
JVM在执行Java程序时,会把它管理的内存划分为若干个的区域,每个区域都有自己的用
途和创建销毁时间,可以分为两大部分,线程私有区和共享区
1丶线程私有区
==程序计数器:==当同时进行的线程数超过CPU数或其内核数时,就要通过时间片轮询分派CPU的时间资源,不免发生线程切换。这时,每个线程就需要一个属于自己的计数器来记录下一条要运行的指令。
==Java虚拟机栈:描述Java方法执行的内存模型,每个方法被执行的时候都会同时创建一个栈帧用于存储局部变量表、操作栈、动态链接、方法出口等信息。==与线程同时创建。每个方法执行时都会创建一个栈帧来存储方法的信息,新调用的方法入栈,返回的出栈,所以栈的大小决定方法调用的可达深度。
本地方法栈,与虚拟机栈作用相似。但它不是为Java方法服务的,而是本地方法。不同虚拟机实现的方法不同。
2丶线程共享区
此区域是用来存储被各线程共享的数据
==方法区:==用于存放加载类的元数据信息,存储已被虚拟机加载的类信息、常量、静态变量即时编译器编译后的代码数据等(这个区域的内存回收目标主要是针对常量池的回收和对类型的卸载)
==堆:==存放对象实例和数组,在虚拟机启动时创建,是垃圾回收的主要区域。
Java虚拟机栈:
1.局部变量(简单的程的执行)
①
②加入了方法的调用
2.数组的内存
在Java中凡是new出来的对象 都存放在堆区
①
②交换两个整数的值与交换数组中两个元素的位置区别
交换两个整数的值
交换数组中两个元素的位置
实则为:方法中参数的传递
当传递的是基本类型的数据的时候 ——值传递(传递的是变量的值)
当传递的是引用类型的数据的时候 ——传递的是地址 (址传递)
本质都是值传递
(2)方法的重载:(判断方法是否构成重载的判断依据)
1 在同一个类中
2 方法名称相同
3 参数列表不同:
①参数的个数不同
②参数的类型不同
③ 参数列表有不同的类型构成,不同类型的顺序不同
注意:方法的返回值不能作为是否重载的依据
1 // 求两个整数的和
2 public static int add(int x , int y ) {
3 return x + y;
4
5 }
6
7 public static int add(int x , int y , int z ) {
8
9 return x + y + z ;
10
11 }
12 public static int add(int x , int y , int z ,int m) {
1314 return x + y + z + m;
15
16 }
17
18 public static double add(int x , double y) {
19
20 return x + y;
21 }
22 public static double add( double y,int x) {
23
24 return x + y;
25 }
jdk5的新特性 可变参数
格式: int … y
可变参数的用法和数组相同
1 public static void main(String[] args) {
2 int s = 0 ;
3 s = add(1,2,5,2,3,6,8);
4 System.out.println(s);
5 }
6 // 求整数的和
7 public static int add(int x , int ... y ) {
8 //可变参数的用法和数组相同
9 int sum = x;
10 for(int i = 0 ; i < y.length; i++) {
11
12 sum += y[i];
13 }
14
15 return sum;
16
17 }
1.可以直接以可变参数作为方法的形参
2.当参数列表中存在可变参数的时候 可变形参必须位于参数列表的末尾
3.可变参数只能传入同种类型的数据
4.可变参数也可构成重载
1 public static int add(int x, int m,int ... y ) {
2 //可变参数的用法和数组相同
3 int sum = 0;
4 for(int i = 0 ; i < y.length; i++) {
5
6 sum += y[i];
7 }
8
9 return sum;
10
11 }
12 public static int add(int x, int m,int y ) {
13 return x + m + y;
14
15 }
可变参数和数组之间不构成重载
数组是引用类型
五、二维数组
1.二维数组的定义:
动态初始化
int[][] arr = new int[5][5];
int[][] arr = new int[5][];
(五行五列的数组;必须有行 ; 实则是多个一维数组)
静态初始化
int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}, {3,6,9}};
特殊形式
//数组定义的特殊形式
int[] x,y[];
x = new int[3];
y = new int[5][];
x是一维数组,y是二维数组。
2.二维数组的基本操作:
int[][] arr = new int[5][5];
int[][] arr1 = new int[][] {{2,1,3,5},{2,5,1},{4,7}};
//赋值
arr[0][0] = 10;
arr[0][1] = 11;
arr[0][2] = 12;
arr[1][1] = 22;
arr[2][3] = 23;
for(int i = 0 ;i < arr1.length;i++) { //外循环相当于行数(遍历地址)
//System.out.println(arr[i]);
for(int j =0 ;j <arr1[i].length;j++) { //针对某一行的数组进行遍历
System.out.print(arr1[i][j]+" ");
} System.out.println();
}
3.二维数组的内存
六、数组相关算法
1. 数组元素的赋值(杨辉三角等)
2. 求数值型数组中元素的最大值、最小值、平均数、总和等
3. 数组的复制、反转、查找(线性查找、二分法查找)
4. 数组元素的排序算法
1.二分查找算法:
在数组中查找指定的元素
前提:数组必须是有序 使用从小到大
思想:
1 public static void main(String[] args) {
2 int[] arr = {‐99,‐54,‐2,0,2,33,43,256,999};
3 int key = 99;//目标元素
4 int head = 0;//开始位置
5 boolean flag = true;
6 int end = arr.length‐1;//结束位置
7 int mid = ‐1;
8 while(head <= end) {
9 mid = (end + head )/2;//中间元素的索引
10 if(key > arr[mid]) {//
11 head = mid + 1;
12 flag =false;
13 }else if(key < arr[mid]) {
14
15 end = mid ‐1;
16 flag =false;
17 }else {//等于
18 flag = true;
19
20 break;
21 }
22
23 }
24 if(flag) {
25 System.out.println("找到目标元素,目标元素的索引"+mid);
26 }else {
27 System.out.println("要查找的元素不存在");
28 }
29 }