Java基础笔记(二)---数组与方法
(1)数组的定义和访问
(1)数组概念
数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。
(2)数组初始化
(1)动态初始化(指定长度)
int[] arr = new int[3];
int arr[] = new int[3];
// 可以拆分
int[] arr;
arr = new int[3];
(2)静态初始化(指定内容)
int[] arr = new int[]{1,2,3,4,5};
// 可以拆分
int[] arr;
arr = new int[]{1,2,3,4,5};
静态初始化省略格式(不能拆分)
int[] arr = {1,2,3,4,5};
(3)Arrays.fill 方法快速初始化
java中的数组初始值都为零,若快速填充一个其他值的数组,即将数组批量填充相同的值,可以用 Arrays.fill 方法,但只能填充一个一维数组,多维数组还得用循环。
import java.util.Arrays;
public class HelloWorld {
public static void main(String[] args) {
int[] arr = new int[5];
Arrays.fill(arr, 1);
System.out.println(Arrays.toString(arr)); // [1, 1, 1, 1, 1]
}
}
虽然Arrays.fill方法不能填充二维数组,不过在下面这种情况下,还是可以用一下的:
int[][] map=new int[4][5];
int[] row={1,2,6,3,6,1,7};
Arrays.fill(map,row);
当row中的数值不固定,也不一定有规律时,可以用Arrays.fill()来填充二维数组,使其每一行都是{1,2,6,3,6,1,7}
(3)数组的访问
(1)索引
每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引 (index),可以通过数组的索引访问到数组中的元素。
(2)数组的长度
每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语句为:数组名.length ,属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数组的最大索引值为数组名.length-1。
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
//打印数组的属性,输出结果是5
System.out.println(arr.length);
}
(3)索引访问数组中的元素
数组名[索引] = 数值,为数组中的元素赋值
变量 = 数组名[索引],获取出数组中的元素
public static void main(String[] args) {
//定义存储int类型数组,赋值元素1,2,3,4,5
int[] arr = {1,2,3,4,5};
//为0索引元素赋值为6
arr[0] = 6;
//获取数组0索引上的元素
int i = arr[0];
System.out.println(i);
//直接输出数组0索引元素
System.out.println(arr[0]);
}
(4)二维数组操作
(1)二维数组初始化
int[][] array1 = new int[10][10];
int array2[][] = new int[10][10];
int array3[][] = { { 1, 1, 1 }, { 2, 2, 2 } };
int array4[][] = new int[][] { { 1, 1, 1 }, { 2, 2, 2 } };
(2)不定长二维数组
int[][] array = new int[3][];
array[0] = new int[1];
array[1] = new int[2];
array[2] = new int[3];
(3)获取二维数组的长度
// 获取二维数组行数(有多少行)
int length1 = array.length;
// 获取二维数组列数(有多少列)
int length2 = array[0].length;
// 获取二维数组的第一维长度(3)
System.out.println(length1);
// 获取二维数组的第一维的第一个数组长度(1)
System.out.println(length2);
(2)数组原理内存图
(1)内存概述
内存是计算机中的重要原件,临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。 Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
(1)声明数组,分配栈内存
int score[]=null;
声明整型数组score,在栈内存中保存了此数组的名称,实际上是保存了对一维内存的引用地址,接下来就要在堆内存中配置数组所需要的内存。
此时,默认值为null,score尚未指向具体的空间,所以score内容未知,无法直接使用。
(2)为数组分配堆内存空间
score=new int[3];
会在堆内存中开辟三个可供保存整数的内存空间,并且把这个堆内存空间的操作地址赋给score变量,以后就可以在堆内存中保存数据。
所以说数组变量score保存的不是数组的实体,而是数组堆内存的参考地址。
如果没有给数组赋值的话,默认值不是null,而是0。
(3)堆栈内存的解释
栈内存只保存数组的名称,然后使用new关键字在堆内存开辟新的内存空间,接着把堆内存的使用权交给栈内存中的名称变量。此外,一个堆内存空间可以同时被多个栈内存空间所指向。一个具体的人就是堆内存,人的名字就是栈内存。
(4)内存分析
整数数据类型所占空间为4个字节,整形数组score的长度为3,则这个数组在堆内存占用的空间3*4=12字节
(2)Java虚拟机的内存划分
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
JVM的内存划分
(3)数组在内存汇总的存储
(1)一个数组内存图
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr); // [I@5f150435
}
以上方法执行,输出的结果是[I@5f150435,这个是什么呢?是数组在内存中的地址。new出来的内容,都是在堆 内存中存储的,而方法中的变量arr保存的是数组的地址
输出arr[0],就会输出arr保存的内存地址中数组中0索引上的元素
程序执行流程
1-main方法进入方法栈执行
2-创建数组,JVM会在堆内存中开辟空间,存储数组
3-数组在内存中会有自己的内存地址,以十六进制数表示
4-数组中有3个元素,默认值为0
5-JVM将数组的内存地址赋值给引用类型变量array
6-变量array保存的是数组内存中的地址,而不是一个具体数值,因此称为引用数据类型。
(2)两个数组内存图
(3)两个变量指向一个数组
(3)数组遍历
(1)数组遍历
将数组中的每个元素分别获取出来
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
}
(2)for循环
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
(3)foreach循环
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
for (int i : arr) {
System.out.println(i);
}
}
(4)数组常见异常
(1)数组越界异常
public static void main(String[] args) {
int[] arr = {1,2,3};
System.out.println(arr[3])
}
创建数组,赋值3个元素,数组的索引就是0,1,2,没有3索引,因此我们不能访问数组中不存在的索引,程序运行后,将会抛出 ArrayIndexOutOfBoundsException 数组越界异常。在开发中,数组的越界异常是不能出现的,一 旦出现了,就必须要修改我们编写的代码。
(2)数组空指针异常
public static void main(String[] args) {
int[] arr = {1,2,3};
arr = null;
System.out.println(arr[0]);
}
arr = null 这行代码,意味着变量arr将不会在保存数组的内存地址,也就不允许再操作数组了,因此运行的时候 会抛出 NullPointerException 空指针异常。在开发中,数组的空指针异常是不能出现的,一旦出现了,就必须要修改我们编写的代码。
(5)数组常见操作
(1)数组反转
(1)数组反转
数组中的元素颠倒顺序,例如原始数组为1,2,3,4,5,反转后的数组为5,4,3,2,1
(2)实现思想
对称位置的元素交换
1-实现反转,就需要将数组对称元素位置交换
2-定义两个变量,保存数组的最小索引和最大索引
3-两个索引上的元素交换位置 最小索引++,最大索引–,再次交换位置
4-最小索引超过了最大索引,数组反转操作结束
(3)实现思路
1-把数组最小索引元素和数组的最大索引元素交换
2-把数组次小索引元素和数组索引次大索引元素交换
3-…
4-定义两个索引,一个指向最小索引,一个指向最大索引
int min = 0; int max = arr.length - 1;
5-遍历数组,让两个索引变化
min++,max–, 交换条件 min < max;
6-交换最小索引元素 和最大索引元素
需要定义三方变量
int temp = arr[min];
arr[min] = arr[max];
arr[max] = temp;
(4)代码实现
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 };
/*循环中定义变量min=0最小索引 max=arr.length‐1最大索引
min++,max‐‐
*/
for (int min = 0, max = arr.length ‐ 1; min <= max; min++, max‐‐) {
//利用第三方变量完成数组中的元素交换
int temp = arr[min];
arr[min] = arr[max];
arr[max] = temp; }// 反转后,遍历数组
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
(2)数组获取最大元素
(1)最大值获取
从数组的所有元素中找出最大值。
(2)实现思路
1-定义变量 max,保存数组0索引上的元素
2-遍历数组,获取出数组中的每个元素
3-将遍历到的元素和保存数组0索引上值的max变量进行比较
4-如果数组元素的值大于了变量的值,变量记录住新的值
5-数组循环遍历结束,变量保存的就是数组中的最大值
(3)代码实现
public static void main(String[] args) {
int[] arr = { 5, 15, 2000, 10000, 100, 4000 }; //定义变量,保存数组中0索引的元素
int max = arr[0]; //遍历数组,取出每个元素
for (int i = 0; i < arr.length; i++) {
//遍历到的元素和变量max比较
//如果数组元素大于max
if (arr[i] > max) {
//max记录住大值 max = arr[i];
}
}
System.out.println("数组最大值是: " + max);
}
(3)数组排序
使用 Arrays.sort 方法
public static void main(String[] args) {
int[] array = { 3, 2, 1, 4, 5 };
Arrays.sort(array);
System.out.println(Arrays.toString(array)); // [1, 2, 3, 4, 5]
}
(6)Java常用API
(1)输出数组:Arrays.toString()
int[] array = { 1, 2, 3 };
System.out.println(Arrays.toString(array));
(2)数组转: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]
(3)数组转Set:Arrays.asList()
String[] array = { "a", "b", "c", "d", "e" };
Set set = new HashSet(Arrays.asList(array));
System.out.println(set);
(4)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);
(5)数组中是否包含某个值:contains()
String[] array = { "a", "b", "c", "d", "e" };
boolean isEle = Arrays.asList(array).contains("a");
System.out.println(isEle);
(6)数组复制:arraycopy()
int array[] = new int[] { 1, 2, 3, 4 };
int array1[] = new int[array.length];
System.arraycopy(array, 0, array1, 0, array.length);
(7)数组合并:addAll()
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);
(8)数组逆序:reverse()
int[] array = { 1, 2, 3, 4, 5 };
org.apache.commons.lang.ArrayUtils.reverse(array);
System.out.println(Arrays.toString(array));
(9)数组元素移除:ArrayUtils.removeElement()
int[] array = { 1, 2, 3, 4, 5 };
int[] removed = org.apache.commons.lang.ArrayUtils.removeElement(array, 3);
System.out.println(Arrays.toString(removed));
(7)数组作为方法参数和返回值
(1)数组作为方法参数
以前的方法中我们所了解的方法的参数和返回值都是使用的基本数据类型。那么作为引用类型的数组能否作为方法的参数进行传递呢,当然是可以的。 数组作为方法参数传递,传递的参数是数组内存的地址。
public static void main(String[] args) {
int[] arr = { 1, 3, 5, 7, 9 };
//调用方法,传递数组
printArray(arr);
}
/* 创建方法,方法接收数组类型的参数 进行数组的遍历 */
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
内存图实例
(2)数组作为方法返回值
数组作为方法的返回值,返回的是数组的内存地址
public static void main(String[] args) {
//调用方法,接收数组的返回值
//接收到的是数组的内存地址
int[] arr = getArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
/* 创建方法,返回值是数组类型
创建方法,返回值是数组类型 return返回数组的地址 */
public static int[] getArray() {
int[] arr = { 1, 3, 5, 7, 9 };
//返回数组的地址,返回到调用者
return arr;
}
内存图
(3)方法的参数类型区别
(1)代码实例1
public static void main(String[] args) {
int a = 1;
int b = 2;
System.out.println(a); // 1
System.out.println(b); // 2
change(a, b);
System.out.println(a); // 1
System.out.println(b); // 2
}
public static void change(int a, int b) {
a = a + b;
b = b + a;
}
(2)代码实例2
public static void main(String[] args) {
int[] arr = {1,3,5};
System.out.println(arr[0]); // 1
change(arr);
System.out.println(arr[0]); // 200
}
public static void change(int[] arr) {
arr[0] = 200;
}
(8)Array类跟数组相关的方法
1-给数组赋值:通过 fill 方法。
2-对数组排序:通过 sort 方法,按升序。
3-比较数组:通过 equals 方法比较数组中元素值是否相等。
4-查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
5-输出数组为字符串:toString方法
6-数组转换为集合:asList
7-把数组复制成成新数组:copyOf
public class T3 {
public static void main(String[] args) {
int n1 [] ={1,6,2,8,5,4,7,3};
int n2 [] ={1,6,2,8,5,4,7,3};
// 1. .equals 比较两个数组是否全等
boolean equals = Arrays.equals(n1, n2);
System.out.println(equals);
// 2. 对n1升序排列
Arrays.sort(n1);
// iter+回车键 快速输出n1
for (int i : n1) {
System.out.print(i);
}
//3. 将数组n1转换为字符串
String s = Arrays.toString(n1);
System.out.println("\n" +s);
//4. 将数组n2中的所有元素全部转变成10
Arrays.fill(n2,10);
for (int i : n2) {
System.out.print(i+",");
}
System.out.println();
//5. 将数组复制成一个长度为6的新数组,类型与原数组保持一致.
int[] n11 = Arrays.copyOf(n1, 6);
for (int i : n11) {
System.out.print(+i);
}
//6. 查询元素key在数组中的下标,(原数组需升序排列)
System.out.println();
int i = Arrays.binarySearch(n1, 6);
System.out.println("数字6在n1数组中的下标为"+i);
}
}
Arrays.asList("aaa","bbb");//5-方法可以将一个数组转换为一个集合;