数组
一、数组
1.
概念: 可以通同时存储多个 相同类型的数据,并且可以对其中的多个数据统一操作。
2.
使用数组的流程:
(1)
声明:指定数组的存储数据类型,同时指定数组名
数据类型
[]
数组名
; // int[] a;
建议写法
// int []a; int a[];
(2)
分配空间:指定数组的 长度
数组名
= new
数据类型
[
长度
];
(3)
使用数组:【基础重点】
a.
数组中存储的数组被称为数组元素。
b.
对数组的操作分为:存元素 和 取元素
c.
对数组的存取元素通过数组名 和下标进行操作:
存元素:
数组名
[
下标
] =
值
;
取元素:
数组名
[
下标
]
d.
对数组的每一个空间进行编号,这个编号被称为下标。
数组的下标范围:
0 ~
数组长度
-1
e.
如果操作数组时,指定的数组下标不在
0~
数组长度
-1
的范围内,编译通过,
运行报错,错误信息为:
java.lang.ArrayIndexOutOfBoundsException(
数组的下标越界
)
f.
数组的遍历:对数组中的元素进行一一访问的过程。
//
用循环的变量 控制 数组的下标
for(int i=0;i<
数组的长度;
i++){
//
通过
a[i]
操作数组的每一个元素
}
获取数组的长度:
数组名
.length
3.
数组具有默认值值,默认值情况如下:【掌握】
(1)
整数:
0
(2)
小数:
0.0
(3)
布尔:
false
(4)
字符:空字符
(\u0000)
(5)
对象
/
引用:
null
4.
数组的其他定义方式:【多练】
(1)
声明的同时分配空间:数据类型
[]
数组名
= new
数据类型
[
长度
];
(2)
显示初始化:数据类型
[]
数组名
= new
数据类型
[]{
值
1,
值
2,
值
3};
注意:
[]
中不能再指定数组的长度,长度有
{}
中值个数决定。
(3)
显示初始化:数据类型
[]
数组名
= {
值
1,
值
2,
值
3};
注意:声明和初始化必须一起完成,同时数组的长度由
{}
中值个数决定。
int[] a ;
a = {1,7,4}; //error
错误
二、数组的内存【难点
+
理解】
1.
数组在内存中空间是连续的。
2.
数组名存储的是 数组在 内存中的首地址。
3.
计算机中的寻址方式:首地址
+
下标
*
每一个存储空间的字节数。
---
》
(
数组名
[
下标
])
4.
数组下标从
0
开始,是为了提高 寻址效率。
5.
数组类型的变量相互赋值,传递的是数组在内存中首地址。
基本数据类型变量相互赋值,传递的是数值。
三、数组的扩容
1.
扩容思想:【理解】
(1)
先申请一个更大空间的新数组,通常新数组长度为原数组长度的
2
倍
(2)
将原数组中的元素进行一一复制到新数组中
(3)
新地址 覆盖 旧地址
2.
数组扩容实现的方式:
(1)
第一种方式
int[] a = new int[]{1,7,4,3};
// 1.
申请新数组 :长度为原有数组的
2
倍
int[] b = new int[a.length*2];
// 2.
将原有数组中内容进行一一拷贝到新数组中
for(int i=0;i<a.length;i++){
b[i] = a[i];
}
// 3.
新的地址覆盖旧的地址
a = b;
~~~
(2)
利用
System.arraycopy(a,0,b,0,a.length); //
完成 数组复制
参数说明:第一个参数:原数组名
第二个参数:原数组拷贝的起始下标
第三个参数:新数组名
~~~java
1
第四个参数:新数组的存储起始下标
第五个参数:拷贝的个数
/
长度
(3)
利用
java.util.Arrays.copyOf(
原数组名
,
新数组的长度
)
;
//
完成新数组的定义
+
数组的复制
参数说明:第一个参数:扩容的数组名
第二个参数:指定新数组的长度
int
[]
a
=
{
1
,
6
,
8
,
3
};
//
利用 工具实现扩容
int
[]
b
=
Arrays
.
copyOf
(
a
,
a
.
length
*
2
);
a
=
b
;
四、可变长参数【阅读源码和
API
时经常遇到】
1.
可变长参数:函数可以接受个数不固定的实参,
jdk5.0
提出的概念。
2.
注意:参数的个数由调用者调用数给定 个数确定;可变长参数可以接受不等数量的相同类型的数据。
3.
语法:
public static
返回值类型 函数名
(
数据类型
...
变量名
){}
4.
使用:可变长参数会自动生成对应类型数组,所以在函数中直接将 可变长参数当做数组应用即可。
public static
void
fun
(
int
...
a
){
//
自动生成一个
int[] a;
System
.
out
.
println
(
"fun
函数被调用
..."
);
System
.
out
.
println
(
"a
数组的长度
"
+
a
.
length
);
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++
){
System
.
out
.
println
(
a
[
i
]);
}
}
5.
语法规定:一个函数中最多只能定义一个可变长参数,并且可变长参数必须定义在形参最后一个位置。
6.
可变长参数:可以提高代码的灵活度。
五、数组的排序【面试重点】
1.
冒泡排序法:将相邻的两个元素进行一一比较,元素大逐步往后移。
(
从小到大排序
)
//
外层控制比较轮数
a.length-1
for
(
int
i
=
1
;
i
<
a
.
length
;
i
++
){
//
内层循环控制每一轮具有比较项
for
(
int
j
=
0
;
j
<
a
.
length
-
i
;
j
++
){
//
将
a[j]
和
a[j+1]
比较
if
(
a
[
j
]
>
a
[
j
+
1
]){
//
交换
int
temp
=
a
[
j
];
a
[
j
]
=
a
[
j
+
1
];
a
[
j
+
1
]
=
temp
;
}
}
}
2.
选择排序:固定一个下标对应的元素,和其他元素进行一一比较,较小数据逐步往前移。
(
从小到大排序
)
//
外层循环:控制比较轮数
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++
){
//
内层循环控制每一轮具体比较内容:前一个比较项
a[i]
for
(
int
j
=
i
+
1
;
j
<
a
.
length
;
j
++
){
//
用
a[i]
和
a[j]
进行比较
if
(
a
[
i
]
>
a
[
j
]){
int
temp
=
a
[
i
];
a
[
i
]
=
a
[
j
];
a
[
j
]
=
temp
;
}
}
}
3.
利用
java.util.Arrays.sort(
数组名
);
进行排序
---
》快速排序
六、二维数组【了解即可】
1.
语法:
(1)
声明:数据类型
[] []
数组名
;
(2)
分配空间:数组名
= new
数据类型
[
行数
] [
列数
]; //
行 又称为高维
列:低维
2.
二维数组的使用:
(1)
通过行和列对二位数组进行访问:数组名
[
行标
] [
列标
]
注意:行标和列表都是从
0
开始
例如:
a[0] [3] //
第
0
行第
3
列的元素
(2)
二维数组也具有默认值,同一维数组
(3)
获取二维数组的行数: 数组名
.length
列数:数组名
[
行标
].length
注意:二维数组是一维数组的一维数组。
3.
二维数组的其他定义方式
(1)
声明的同时并分配空间:数据类型
[][] [] []
数组名
= new
数据类型
[
行数
] [
列数
];
(2)
显示初始化:数据类型
[] []
数组名
= new
数据类型
[] []{{
值
1,
值
2},{
值
3,
值
4},{
值
5,
值
6}};
注意:后面
{}
中
{}
的个数决定行数,所以
[] []
中个不能再制定行数和列数。
(3)
显示初始化:数据类型
[] []
数组名
= {{
值
1,
值
2},{
值
3,
值
4}};
注意:声明和初始化必须一起完成。
4.
不规则的二维数组
(1)
概念:每一行的列数不相同
(2)
不规则的二维数组的定义方式:
a.
数据类型
[] []
数组名
= new
数据类型
[
行数
] []
;
数组名
[0] = new
数据类型
[
长度
];
数组名
[1] = new
数据类型
[
长度
];
....
注意:二维数组定义可以只指定行数
/
高维,但是不能只指定列数
/
低维
b.
数据类型
[] []
数组名
= {{
值
1},{
值
1,
值
2,
值
3},{
值
1,
值
2}};