数组定义:通过连续的存储空间,存储相同类型的数据集合。
内存存储:有序—》索引:递增有序
存储内容:固定–》随机访问:高效
内存存储结构:吃内存,保证内存连续存储空间够。
元素类型相同:元素所占内存宽度一致,创建对象指向堆的地址,索引从0开始
声明一个变量–变量指向一个数创建出来的数组对象–》对象存储的是当前对象的引用地址。引用的是0索引上的元素地址。
元素的地址=首元素地址+(索引*元素宽度)
/**
* @author renyuhua
* @date 2021年09月15日 9:37
* 1、数组的定义方式
* int[] arrs;
* String strs[]; 不推荐
* 2、初始化:
* 静态初始化:
* a:
* int[] arrs = new int[]{1,2,3};
* [I@6d6f6e28 class对象名称+hashcode值
* [: 表示是数组类型
* I: 表示类型是int
* @: 表示打印的地址
* 6d6f6e28: 表示hashcode值
* b:
* String[] s = {"数据结构"};
* 动态初始化:
* //声明一个能够存储5个元素的int类型的数组,把当前的数组的引用给向ars这个变量
* int[] ars = new int[5];
* 常见问题:
* a、声明数组的时候,动态初始化前不指定长度
* b、给数字重新赋值的时候,通过{}创建数字对象
* int[] ars = new int[5]; ars = {1}; //这里会报编译出错
*
*/
public class ArrayTest {
public static void main(String[] args) {
int[] arrs = new int[]{1,2,3};
System.out.println(arrs);
String[] s = {"数据结构"};
//声明一个数组的时候不循允许 ars = {1}; 重新赋值
int[] ars = new int[5];
ars = new int[]{1,2,3,4};
System.out.println(ars);
}
}
数组常见属性
length:
1、数组长度。2、数组存储的元素的个数
2、有序:通过索引可以获取属性、修改属性,从0开始
3、size=length --------------> 0<=索引<=length-1
/**
* @author renyuhua
* @date 2021年09月15日 11:00
* 测试数组的属性:
* 数组越界异常:通过索引获取数组元素时,超过了索引的范围 [0,length-1]
*/
public class ArrayProperty {
public static void main(String[] args) {
// 1、声明一个int类型的数组
// 数组的长度就会被确定
int[] array = new int[]{1,2,3};
// 2、获取当前数组的源数个数,获取当前数组的长度
System.out.println("当前数组的长度是:"+array.length);
// 3、通过索引获取指定位置上的元素
System.out.println("获取索引是2的元素:"+array[1]);
String[] strings = new String[10];
System.out.println(strings.length);
/*
System.out.println(strings[1]);
检查信息:报告任何数组字段或变量的内容是读但不写,或写但不读。
这种不匹配的读和写是没有意义的,可能表示已死的、不完整的或错误的代码。
*/
}
}
对于数组的内存分析
/**
* @author renyuhua
* @date 2021年09月15日 11:18
*/
public class ArrayMemory {
public static void main(String[] args) {
int[] array = new int[5];
// 将10赋值给内存中索引是2的元素
array[2] = 10;
System.out.println(array.length);
System.out.println(array[0]);
System.out.println(array[2]);
/*
栈: 存储的是局部变量,后进先出,分配main方法栈,存储array,引用数组对象
在堆内存中开辟一个长度为5的数组空间,创建数组对象的时候指定长度,当前对位置上的元素都是当前数组对应类型的默认值
array会指向当前堆内存创建出来的数组的地址,会引用到这个地址,拿到的是当前0索引上的这个元素的地址,根据索引快速获取每一个u元素地址的索引,快速访问到每一个位置对应的当前的元素
array[2] = 10; 找0索引 元素的地址=首元素地址+(索引*元素宽度) 替换10
堆: 所有的引用类型的数据都会存在堆内存当中
*/
}
}
为什么数组是不可变的
数组的长度一旦指定是不可改变的
老数组指向新的数组
array = new int[20];
数组的增删查改以及迭代的方式
import java.util.Arrays;
/**
* @author renyuhua
* @date 2021年09月15日 13:17
* 数组的长度一旦指定无法修改
* 针对于数组的增删改查
*/
public class ArrayUpdate {
public static void main(String[] args) {
int[] array = new int[]{11,44,5,66};
System.out.println(array[3]);
array[0] = 10;
// 遍历数组的输出
System.out.println(Arrays.toString(array));
/*
数组长度不可变,所以给array新增元素只能通过重新开辟空间的方式
*/
// 删除元素
array[2] = 0;
// 普通for循环: [0,array.length)
for (int i = 0; i < array.length; i++) {
System.out.println("i:"+array[i]);
array[i] += 2;
System.out.println("i+2:"+array[i]);
}
System.out.println(Arrays.toString(array));
// 增强for循环 foreach,无法获取索引,人为指定,将每个元素赋值给num
int index = 0;
for (int num : array) {
System.out.println("foreach:"+index+":"+num);
index++;
}
}
}
多维数组
import java.util.Arrays;
/**
* @author renyuhua
* @date 2021年09月16日 9:44
* 多维数组的创建、初始化、内存分析
* 在java中存在一维数组和n维数组
* 二维数组的动态初始化:
* type[][] name = new type[m.length][n.length];
* 就是一个一维数组,只不过每个位置上的元素又是一个一维数组而已。
*/
public class ArrayMultidimensional {
public static void main(String[] args) {
// 二维数组的声明
int[][] arrays = new int[2][3];
System.out.println(Arrays.toString(arrays[0]));
System.out.println(arrays[0][1]);
// 创建了一个一维数组,这个数组的长度是三个,每个数组上都是一个新的一维数组,这个数组的长度是2。
String[][] strings = new String[][]{{"你好","舟舟"},{"嘿嘿","哈哈"},{"宇华","喜喜"}};
System.out.println(Arrays.toString(strings[1]));
// 创建了一个一维数组,这个数组的长度是三个,每个数组上都是一个新的一维数组,这个数组的长度是2。
String[][] strings1 = {{"你好","舟舟"},{"嘿嘿","哈哈"},{"宇华","喜喜"}};
System.out.println(Arrays.toString(strings[0]));
// 创建了一个长度是2的一维数组,每个位置上的元素也是一个数组对象
int[][] array = new int[2][];
System.out.println(Arrays.toString(array[0]));
array[0] = new int[3];
array[1] = new int[5];
System.out.println(Arrays.toString(array));
System.out.println(array[0][1]);
}
}
二维数组的CRUD迭代
/**
* @author renyuhua
* @date 2021年09月16日 10:07
*/
public class ArrayMultUpdate {
public static void main(String[] args) {
// 创建的时候需要指定一维数组的长度
int[][] arrays = new int[3][];
arrays[0] = new int[]{1,2,3};
arrays[1] = new int[]{4,5,6};
arrays[2] = new int[]{7,8,9};
// 二维数组的迭代
for (int i = 0; i < arrays.length; i++) {
for (int j = 0; j < arrays[i].length; j++) {
System.out.println(arrays[i][j]);
}
System.out.println();
}
// 先遍历一维数组,把每个值迭代到 a,再把a的每个值迭代到 b
for (int[] a : arrays) {
for (int b: a ) {
System.out.println(b);
}
System.out.println();
}
}
}
关于可变参数–简化开发
/**
* @author renyuhua
* @date 2021年09月16日 10:19
*/
public class ArrayVariableParameter {
public static void main(String[] args) {
int num1 = 1;
int num2 = 2;
add(new int[]{num1,num2});
adds("",num1,num2);
}
public static void add(int[] num){
int result = 0;
for (int n : num){
result += n;
}
System.out.println(result);
}
/**
* jdk1.5之后的改变。
* 可变参数的定义一定要放在末尾。
* 可变参数一定要保证在形式参数的列表的末尾。
* 对于参数列表而言,必须要保证形参列表中有且只能有一个可变参数。
* @param num
*/
public static void adds(String string,int ... num){
int result = 0;
for (int n : num){
result += n;
}
System.out.println(result);
}
}
关于可变参数的一些坑
最近最优原则
byte–>short–>int–>long–>float–>double(基本数据类型)–>包装类
char–>int
方法的调用顺序:
1、第一匹配顺序完全匹配
2、第二匹配原则最近最优
3、第三匹配顺序包装类
4、第四匹配顺序可变参数
可变参数继承
/**
* @author renyuhua
* @date 2021年09月16日 11:24
* null可以转换为任意的引用类型
* 避免程序出现二义性
*/
public class ArraySelect {
public static void main(String[] args) {
//fun("",null);
}
public static void fun(String str,String ... strings){
System.out.println();
}
public static void fun(String str,Integer ... integers){
System.out.println();
}
}
关于null值和引用类型的转换关系
/**
* @author renyuhua
* @date 2021年09月16日 13:37
* null值转化为引用类型时,需要注意最近最优。
*/
public class ArrayExchange {
public static void main(String[] args) {
// 调用的是第二个invoke方法,null可以转换为任意的引用类型
// 引用类型: 最近最优,String是Object的子类,null离String更近一些,先找父亲,再找爷爷
invoke(null,1);
}
static void invoke(Object object,Object ... args){
System.out.println();
}
static void invoke(String string,Object object,Object ... args){
System.out.println();
}
}
稀疏(矩阵)数组和二维数组的转换
行 | 列 | 值(元素个数) |
---|---|---|
15 | 15 | 19 |
原来的二维数组15行,15列,用了19个元素 | ||
4 | 8 | 1 |
5 | 7 | 2 |
现在用行列值区分 |
/**
* @author renyuhua
* @date 2021年09月16日 13:55
*/
public class Convert {
static int[][] array;
static {
array = new int[15][15];
array[4][8] = 1; array[7][5] = 2; array[5][7] = 2;
array[7][7] = 1; array[5][8] = 1; array[7][8] = 2;
array[6][4] = 1; array[7][9] = 2; array[6][6] = 2;
array[8][7] = 1; array[6][8] = 2; array[8][8] = 2;
array[6][9] = 1; array[8][9] = 1; array[8][10] = 1;
array[9][7] = 2; array[9][8] = 2; array[10][6] = 1;
array[10][8] = 1;
}
public static void main(String[] args) {
System.out.println(toString(array));
int[][] sparesMatrix = convertSparesMatrix(array);
System.out.println(toString(sparesMatrix));
int[][] arrays = convertArray(sparesMatrix);
System.out.println(toString(arrays));
}
private static int[][] convertArray(int[][] sparesMatrix) {
int[][] arrays = new int[sparesMatrix[0][0]][sparesMatrix[0][1]];
for (int i = 1; i < sparesMatrix.length; i++) {
arrays[sparesMatrix[i][0]][sparesMatrix[i][1]] = sparesMatrix[i][2];
}
return arrays;
}
private static int[][] convertSparesMatrix(int[][] array) {
// 拿到非0元素的个数
int noZeroNum = 0;
for(int[] rows : array) {
for (int num : rows) {
if (num!=0){
noZeroNum++;
}
}
}
int[][] sparesMatrix = new int[noZeroNum+1][3];
// 第一行已经填充了列
sparesMatrix[0][0] = 15;
sparesMatrix[0][1] = 15;
sparesMatrix[0][2] = noZeroNum;
int noZeroRow = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j]!=0){
noZeroRow++;
sparesMatrix[noZeroRow][0] = i;
sparesMatrix[noZeroRow][1] = j;
sparesMatrix[noZeroRow][2] = array[i][j];
}
}
}
return sparesMatrix;
}
private static String toString(int[][] args){
StringBuilder ret = new StringBuilder();
for(int[] rows : args){
for(int num : rows){
ret.append(num+"\t");
}
ret.append("\r\n");
}
return ret.toString();
}
}