数组
数组概述
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,它按照一定的先后次序排列而成
- 其中,每一个数据被称作一个数组元素,每个数组元素可以通过一个下标来访问它
数组的声明与赋值
- 必须先声明数组变量,才能在程序中使用,声明格式如下(两种方式二选一):
- 数组的类型[] 数组名;
- 数组的类型 数组名[];
- Java中使用new操作符新建数组:
数组的类型[] 数组名=new 数组的类型[数组大小]; - 数组的元素是通过索引访问的,数组索引从零开始
- 获取数组长度:数组名.length
声明与赋值示例
public class array {
public static void main(String[] args) {
int[] num=new int[10];//也可以这样定义
//int num[]; num=new int[10];
int sum=0;
for (int i : num) {
num[i]=i;
}
System.out.println(sum);
}
}
在上面的代码块中出现了for(int i:num){}的用法
它相当于对数组从头到尾的元素执行一遍括号内的操作,即给下表为i的元素赋值为i,快捷键为数组名.fori
另外,也可以直接用for循环,快捷键为数组名.for
内存分析
栈
- 存放new的对象与数组
- 可以被所有的线程共享,不会存放别的对象引用
堆
- 存放基本变量类型(包含这个基本类型的具体数值)
- 引用对象的变量(会存放这个引用在堆里面的具体地址)
方法区
- 可以被所有线程共享
- 包含了所有的class和static变量
案例
比如在上面的代码块中,我们创建了一个数组,内存分析如下图:
十个小方块内分别被赋值0,1,2,3,4,5,6,7,8,9
数组的三种初始化方式
- 静态初始化
int[] a={1,2,3};
Man[] mans={new Man(1,1),new Man(2,2)}//这种用法以后会讲
- 动态初始化
int[] a=new int[2];
a[0]=1;
a[1]=2;
- 默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此,数组一被分配空间,七中的每个元素就按照实例变量同样的方式初始化(如元素为int类型的数组初始值为0)
数组的四个基本特点
- 长度确定,一经创建大小不可改变
- 元素必须是相同类型
- 数组中的元素可以是基本类型也可以是引用类型
- 数组变量属于引用类型,数组也可以看成对象,每个元素相当于成员变量,数组本身就是对象,Java中对象在堆中,如此数组无论保存原始类型还是其它对象类型,数组对象本身在堆中
数组边界
数组的下标范围是[0,length-1],如果越界就会报错:
ArrayIndexOutOfBoundsException:数组下标越界异常
数组使用
for-each循环
即遍历数组
public class array {
public static void main(String[] args) {
int arrays[]={1,2,3,4,5};
for(int array:arrays){
System.out.println(array);
}
}
}
该程序会输出
1
2
3
4
5
创建此循环的快捷键:数组名.fori
数组作方法入参
该程序输出结果与上面代码块相同
public class array {
public static void main(String[] args) {
int arrays[]={1,2,3,4,5};
printarray(arrays);
}
public static void printarray(int[] arrays){
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
}
}
数组作为返回值
我们来写一个反转数组的程序,即将数组倒序输出
在上面代码的基础上添加一个反转数组方法
public class array {
public static void main(String[] args) {
int arrays[]={1,2,3,4,5};
int[] reverse=reverse(arrays);//接收返回的数组
printarray(reverse);
}
public static void printarray(int[] arrays){
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
}
//反转数组
public static int[] reverse(int[] arrays){
int[] result=new int[arrays.length];
//反转的操作
for (int i=0;i< arrays.length;i++)
{
result[arrays.length-i-1]=arrays[i];
}
return result;//返回一个数组
}
}
多维数组
简介
- 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,每个元素都是一个一维数组
- 定义二维数组int a[ ][ ]= new int[2][5];
- 解析:以上二维数组a可以看成一个两行五列的数列
- 多维数组的使用:int[0][0]表示该数列第一行第一个数
定义一个二维数组
public class array {
public static void main(String[] args) {
int[][] arr={{1,2},{2,3},{3,4}} ;
}
}
很形象的图解:
而当我们输出arr[0]时,却看到的是以下结果:
这是什么意思?其实是因为System.out.println();不能直接输出数组中所有元素,于是他输出了它的哈希code(不懂以后讲)
二维数组的输出
首先,我们先了解二维数组的长度:
输出二维数组,我们可以用嵌套循环:
public class array {
public static void main(String[] args) {
int[][] arr={{1,2},{2,3},{3,4}} ;
for (int i = 0; i < arr.length ; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}
运行结果如图所示:
Array类
即数组的工具类java.util.Arrays,Arrays类中的方法都是static修饰的静态方法,在使用时可以直接使用类名调用,不用使用对象
常用功能
- 给数组赋值:fill方法
- 对数组排序:sort方法(升序)
- 比较数组:equals方法比较数组中元素是否相等
- 查找数组元素:binarySearch方法对排序好的数组进行二分查找
JDK帮助文档
Arrays中有很多方法,我们可以在帮助文档中查找其用法
在这里我分享一下这个文件:链接:https://pan.baidu.com/s/1VuCU0uRhk2vRcn_7zAsQ2g
提取码:yi4r
打印数组元素的方法
在上面我们知道,System.out.println();不能输出数组,而Java中为我们准备了一个输出数组的方法
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[][] arr={{1,2},{2,3},{3,4}} ;
System.out.println(Arrays.toString(arr[0]));
}
}
运行结果如图所示:
它还为我们在两边加上了[ ]
自行实现打印数组的方法
Java中的方法很多,有时我们自己就能完成的操作并不需要使用方法,我们可以自己定义一个输出数组的方法:
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[][] arr={{1,2},{2,3},{3,4}} ;
printArray(arr[0]);
}
public static void printArray(int a[]){
for (int i = 0; i < a.length; i++) {
if(i==0){
System.out.print("[");
}
if(i==a.length-1){
System.out.print(a[i]+"]");
}else{
System.out.print(a[i]+",");
}
}
}
}
如图,成功实现:
将数组按从从小到大顺序排列的方法
随意创建一个数组,使用sort方法排序:
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[] arr={6,154,656,45,46,82,654} ;
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
如图,成功
给数组赋值的方法
可以利用fill方法给数组赋值:
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[] arr={6,154,656,45,46,82,654} ;
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
Arrays.fill(arr,0);
System.out.println(Arrays.toString(arr));
}
}
还可以只对数组的一部分赋值:
选择这一个方法
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[] arr={6,154,656,45,46,82,654} ;
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
Arrays.fill(arr,2,4,0);
System.out.println(Arrays.toString(arr));
}
}
输出结果为:
为什么是这样?我们按住CTRL左键点击fill方法,查看它的源码:
所以上面的代码相当于从arr[2]到arr[3]被赋值为0
冒泡排序
- 比较数组中两个相邻的元素,如果第一个比第二个大,就交换他们的位置
- 每一次比较,都会产出一个最大,或者最小的数字
- 下一轮可以少一次排序
- 依次循环,直到结束
代码实现:
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[] arr={6,154,656,45,46,82,654} ;
int[] sort=sort(arr);
System.out.println(Arrays.toString(arr));
}
public static int[] sort(int[] arr){
int temp=0;//临时变量,交换两个书的值时使用
//经过第一轮,最右边的数最大,第二轮后,从右边数第二个数为第二大,因此,第n-1轮,就可以少进行n-1次比较
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++) {
if(arr[j+1]<arr[j])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
return arr;
}
}
结果:
当然,如果这个数组本身就已经排序好,这样会浪费时间,我们可以稍加改造,以优化程序:
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[] arr={6,154,656,45,46,82,654} ;
int[] sort=sort(arr);
System.out.println(Arrays.toString(arr));
}
public static int[] sort(int[] arr){
int temp=0;
boolean flag=false;
for (int i = 0; i < arr.length-1; i++) {
for (int j = 0; j < arr.length-1-i; j++)
{
if(arr[j+1]<arr[j])
{
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=true;//如果进入此语句,就说明原本数组未排序,改变flag的值
}
}
if(flag==false)//如果flag未被改变,说明原本数组已排号,直接退出循环,无需进行第二次循环
{
break;
}
}
return arr;
}
}