快捷键:
生产输出语句: 表达式.sout
数组遍历:
数组名.fori: 正着遍历
数组名.forr: 倒着遍历
java.util.Arrays
1、数组定义和访问
1.1 容器的概念
变量中只能存储一个数据,新的数据进来,老的数据将被替换,如果需要存储多个数据,需要使用容器。
容器概念
容器:是将多个数据存储到一起,每个数据称为该容器的元素。
生活中的容器:水杯,衣柜,鞋柜,教室
1.2 数组
1.概念:数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。
java中的数组就是一个容器,可以存储多个数据,但是数据的类型必须一致
2.特点:
(1)可以存储多个数据
(2)多个数据的类型必须保持一致
(3)数组一旦创建,长度是永远不可以发生改变
1.3 数组的定义
方式一:
数组存储的数据类型[] 数组名字; //推荐使用
方式二:
数组存储的数据类型 数组名字[];
练习:
//定义int变量num
int num;
//System.out.println(num);//错误:变量未初始化,不能使用
//定义一个存储int类型数组的变量arrayA
//int类型数组: 该容器中只能存储的是int类型的数字
int[] arrayA;
//System.out.println(arrayA);//错误的: arrayA只是一个用来存储数组的变量,但是目前没有向arrayA中存储数组
1.4 数组的初始化
方式一: 数组动态初始化
数组动态初始化就是只给定数组的长度,由系统给出默认初始化值
格式:
数组存储的数据类型[] 数组名字 = new 数组存储的数据类型[长度];
int[] arr = new int[3]; //定义可以存储3个整数的数组容器
注意:数组有定长特性,长度一旦指定,不可更改。
方式二: 数组静态初始化
在创建数组时,直接确定数组元素
//标准格式:
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3...};
2.注意:
(1)右侧[]中不能写长度: JVM会根据{}中元素的数量计算/推导出数组的长度
只要右侧[]中写长度,就会报错
(2){}中的每个元素之间有逗号(英文状态)隔开,最后一个元素后面没有逗号
int[] arr = new int[]{1,2,3,4,5};
//简化格式:
数据类型[] 数组名 = {元素1,元素2,元素3...};
int[] arr = {1,2,3,4,5};
1.5 数组的访问
索引: 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。
格式:
数组名[索引]
数组的长度属性:
每个数组都具有长度,而且是固定的,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);
}
索引访问数组中的元素:
数组名[索引]=数值,为数组中的元素赋值
变量=数组名[索引],获取出数组中的元素
/*
注意:
1.数组名称保存数组在堆内存中的地址值
2.通过数组名称找到堆内存中的具体数组,然后通过索引编号找到对应的具体的某个元素
数组元素有默认值:
1.整数: 0
2.小数: 0.0
3.字符: 空白字符
4.布尔: false
*/
public static void main(String[] args) {
//定义存储int类型数组,赋值元素1,2,3,4,5
int[] arr = {1,2,3,4,5};
System.out.println(arr); //[I@1b6d3586 [:数组、I:int @:在哪
//为0索引元素赋值为6
arr[0] = 6;
//获取数组0索引上的元素
int i = arr[0];
System.out.println(i);
//直接输出数组0索引元素
System.out.println(arr[0]);
}
2、数组原理内存图
Java虚拟机的内存划分
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
JVM的内存划分:
1.方法区: 存储可以运行的class文件。
2.方法栈: 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。
3.堆内存 存储对象或者数组,new来创建的,都存储在堆内存。
4.寄存器 给CPU使用,和我们开发无关 不关心
5.本地方法栈 JVM在使用操作系统功能的时候使用,和我们开发无关。 不关心
//创建int数组one,长度为2
int[] one = new int[2];
/*
数组变量one保存的是数组在内存空间的地址值,
赋值给新的数组变量two,导致数组变量one和two保存相同的内存地址,
操作的是同一个数组
*/
int[] two = one;
3、数组操作的常见问题
3.1 数组越界异常
/*
数组操作的常见问题一:
数组索引越界(超出了范围)异常
1.问题描述: java.lang.ArrayIndexOutOfBoundsException类,数组索引越界异常类
2.产生原因:
使用索引编号访问数组元素时,给出的索引编号不存在(超出了范围)
索引编号范围: 最小值是0,最大值是数组长度 减 1 (one.length - 1)
3.解决方案:
根据控制台的打印信息,找到出现问题的索引,进行修改
*/
public class Demo01ArrayProblem {
public static void main(String[] args) {
//创建int数组array,并初始化
//int[] one = new int[]{100,200,300};
int[] one = {100,200,300};//100的索引编号是0,200的索引编号是1,300的索引编号是2
System.out.println(one);//数组名称one代表数组的内存地址值:[I@1540e19d
System.out.println(one[0]);//100
System.out.println(one[1]);//200
System.out.println(one[2]);//300
//System.out.println(one[5]);//索引5: 不存在,报出数组索引越界异常
}
}
3.2 数组空指针异常
/*
数组操作的常见问题二:
空指针异常
1.问题描述: java.lang.NullPointerException类,空指针异常类
2.产生原因:
null是一个引用类型的常量,可以给任意类型引用变量赋值,
当把null赋值给数组变量one之后,数组变量one将不再指向堆内存空间的任何数组,
也就不可以通过one再访问数组元素,只要访问,报出空指针异常
3.解决方案:
(1)不要通过值为null的数组变量,访问数组元素
(2)根据控制台打印的相关异常信息,找到数组变量是null的地方进行修改,
让数组变量指向一个堆内存空间的数组,就可以访问数组元素了
*/
public class Demo02ArrayProblem {
public static void main(String[] args) {
//创建int数组array,并初始化
//int[] one = new int[]{100,200,300};
int[] one = {100,200,300};//100的索引编号是0,200的索引编号是1,300的索引编号是2
System.out.println(one);//数组名称one代表数组的内存地址值:[I@1540e19d
System.out.println(one[0]);//100
System.out.println(one[1]);//200
System.out.println(one[2]);//300
one = null;
System.out.println(one);//null
//System.out.println(one[0]);//错误: 控制针异常
}
}
4、练习
4.1 数组遍历
就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。
public class Demo01EachArray {
public static void main(String[] args) {
//创建int数组array,并初始化
//10的索引编号是0,20的索引编号是1,30的索引编号是2,50的索引编号是3
int[] array = {10,20,30,50/*,60,70,80,90,100*/};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
System.out.println(array[3]);
System.out.println("-----------");
//发现: 以上代码重复,只有索引0到3是不同的
//可以使用for循环打印0到3的数字
for (int i = 0; i < 4; i++) {
System.out.println("索引编号: "+i+", 对应的元素值: "+array[i]);
}
System.out.println("-----------");
//发现: 以上for循环中数字4写死了,可以使用数组的长度代替
for (int i = 0; i < array.length; i++) {
//System.out.println("索引编号: "+i+", 对应的元素值: "+array[i]);
System.out.println(array[i]);
}
}
}
5、Arrays用法
5.1 Arrays类概述
Arrays类位于 java.util 包中,主要包含了操纵数组(比如排序和搜索)的各种方法。该类还包含一个静态工厂,允许将数组视为列表。
如果指定的数组引用为null,则此类中的方法都抛出NullPointerException,除非另有说明。
5.2 Arrays类常用方法
//数组转List
List<T> asList(T... a):返回由指定数组构成的大小固定的列表,该列表不能使用add和remove方法改变长度
//查找
int binarySearch(Object[] a, Object key):使用二分查找元素的索引
//生成子数组
T[] copyOfRange(T[] original, int from, int to):复制数组,并且指定开始/结束索引
T[] copyOf(T[] original, int newLength):复制数组,并且指定复制长度
//填充数组
void fill(Object[] a, Object val):使用指定元素填充数组
void fill(Object[] a, int fromIndex, int toIndex, Object val):使用指定数组填充数组,并且指定填充的开始/结束索引
//排序
static void sort(byte[] a) //将指定的数组按升序排序。
static void sort(byte[] a, int fromIndex, int toIndex) //按升序对数组的指定范围进行排序。
void sort(Object[] a):对数组排序,需要实现数组元素的Comparable接口
void sort(Object[] a, int fromIndex, int toIndex):对指定开始/结束索引的数组排序,需要数组元素实现Comparable接口
void sort(T[] a, Comparator<? super T> c):对数组排序,需要数组元素实现Comparator接口
void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c):对指定开始/结束索引的数组排序,需要实现数组元素的Comparator接口
//打印数组
String toString(Object[] a) //返回指定数组的内容的字符串表示形式
//数组转Stream
static Stream<T> stream(T[] array):数组转为流
static IntStream stream(int[] array):int数组转为流,还有DoubleStream和LongStream