Java数组相关
数组概述
数组的定义
-
数组是相同类型数据的有序集合
-
数组描述的是相同类型的若干个数据,按照一定先后次序组合而成
-
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们,下标从0开始
例子:一个球队中的不同号码的队员
代码
public static void main(String[] args) {
int[] nums={10,20,30,40,50};
for(int i=0;i<5;i++)
{
System.out.println("这是第"+(i+1)+"个元素,其下标为:"+i);
}
}
运行结果
数组特点
- 数组长度确定。一旦被创建,大小不可变
- 元素必须是相同类型的
- 元素的类型可以是任何类型,基本数据类型或者引用类型
- 数组属于对象,处于堆中,数组元素相当于对象的成员变量,它的名字存在栈中,指向实际位置在堆中的元素
数组的边界问题
合法的下标区间为[0 — length-1],越界就会报错
public static void main(String[] args) {
int[] nums = new int[10];
System.out.println(nums[11]);
}
会报异常:ArrayIndexOutOfBoundsException
数组下标越界
数组声明创建
数组的声明创建
- 首先必须声明数组变量,才能在程序中使用数组。下面是声明数组变量的语法
dataType[] arrayname;//首选方法,java风格
//或者
dataType arrayname[];//效果相同,但是非首选。c/c++风格
- Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayname = new dataType[arraySize];
- 数组的元素是通过索引访问的,数组索引从0开始
- 获取数组长度
arrays.length();
小例子
public static void main(String[] args) {
//声明数组
int[] nums;
//开辟空间
nums =new int[5];
for(int i=0;i<5;i++)
{
nums[i]=i;//给数组元素赋值
}
for(int i=0;i<5;i++)
{
System.out.println("这是第"+(i+1)+"个元素,值为"+nums[i]+",其下标为:"+i);
}
//计算数组的和
int i;
int sum=0;
//nums.length可以获取数组的长度
for (i = 1; i<=nums.length; i++)
{
sum += nums[i-1];
}
System.out.println("数组的和为:"+sum);
}
输出结果
三种初始化以及内存分析
Java内存
- 堆:
- 存放new的对象和数组
- 可以被所有的线程共享,不会存放避恶恶的呃对象引用
- 栈:
- 存放基本数据类型
- 引用对象的变量(会存放这个引用在堆里面的具体地址)
- 比如数组只声明了,却没有new
- 因此如果直接输出数组会输出对象的名字
- 方法区:
- 可以被所有的线程所共享
- 包含了所有的class和static变量
声明数组时,在栈中注册array
开辟空间时,(new关键字),在堆中开辟空间
静态初始化
//声明创建以及赋值一起做
int a[]={0,1,2,3,4,5};
int[] a={0,1,2,3,4,5};
动态初始化
//声明创建空间一起做,默认初始值为0,需要手动赋值
int a[]=new int[5];
a[2]=10;
数组的默认初始化
数组为引用类型,它的元素相当于类的实例变量,因此一经分配空间,就会被隐式初始化
//一经初始化,a[0]到a[4]的值都会被初始化为0
int a[]=new int[5];
数组使用
for-each循环
代码
public static void main(String[] args) {
int a[]={1,2,3,4,5};
for (int x : a) {
System.out.println(x);
}
}
运行结果
数组作方法参数以及返回值
数组也可以用作方法的参数以及返回值
小例子
public static void main(String[] args) {
int a[]={1,2,3,4,5};
printArrays(reverse(a));
}
//反转数组
public static int[] reverse(int[] Arrays)
{
int a[]=new int[Arrays.length];
for(int c=0;c<Arrays.length;c++){
a[Arrays.length-1-c]=Arrays[c];
}
return a;
}
//输出数组元素
public static void printArrays(int[] Arrays)
{
for (int x : Arrays) {
System.out.print(x+" ");
}
}
运行效果
这里提一嘴,数组入参,是引用传参,如果在函数中修改数组的值,会直接将原数组的数修改
多维数组
以二维数组为例:二维数组可以理解为一维数组的每一个元素都是一个数组
- 二维数组
//一个两行五列的数组
int[][] a = new int[2][5];
小例子
public static void main(String[] args) {
int[][] a={{1,2},{2,3},{3,4}};
/*
实际情况
a[0][0],a[0][1]中存储的是 1,2
2,3
3,4
*/
//输出数组元素
System.out.println(a[0][1]);
//函数输出二维数组的值
printArrays(a);
}
//输出数组元素
public static void printArrays(int[][] Arrays)
{
for (int[] x : Arrays) {
for (int a : x) {
System.out.print(a+" ");
}
System.out.println();
}
}
运行结果
Arrays类
java.util中的Arrays类
Arrays类中实现了好多方法,Arrays类被用static修饰,因此调用该类的方法需要直接使用类名进行调用
- 给数组赋值:fill方法
- 最数组排序:通过sort方法,默认升序
- 比较数组:通过equals方法比较数组中元素值是否相等
- 查找元素:通过binarySearch方法能对排好序的数组进行二分查找法操作
public static void main(String[] args) {
int a[]={10,2,55,85,45,78};
int a2[]={10,2,55,85,45,78};
//对数组进行排序,升序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
//用fill对数组进行赋值
Arrays.fill(a,0);
//fill方法重载
Arrays.fill(a,1,3,9);
System.out.println(Arrays.toString(a));
//equals方法的使用
if(Arrays.equals(a,a2)){
System.out.println("这两个数组一样");
}
else{
System.out.println("这两个数组不一样");
}
//binarySearch方法来查找数字
//首先需要排好序
Arrays.sort(a2);
System.out.println("这里输出的是待查找数字的下标:"+Arrays.binarySearch(a2,45));
}
运行结果
经典排序算法
- 江湖上人尽皆知!!!
- 插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序
冒泡排序
思想类似泡泡从水底产生,不断地浮上水面,浮到水面变成最大的
双层嵌套循环,时间复杂度:O(n^2)
public static void main(String[] args) {
//冒泡排序演示
int []a={12,55,89,57,15,21,3,78,6};
System.out.println(Arrays.toString(a));
bubble(a);
System.out.println(Arrays.toString(a));
}
//冒泡排序主函数
public static void bubble(int[] arrays){
int temp = 0;
int count = 0;
//每一趟都能找出一个当前未排好序元素中的最大
for(int i=0;i<arrays.length;i++)
{
//每趟排序后,需要排序的数字就少一个,不需要每一趟排序都到最后一个数
for (int j=0;j<arrays.length-1-i;j++)
{
//每趟比较相邻地两个元素,若下标小的大于下标大的,则交换位置
count++;
if(arrays[j]>arrays[j+1])
{
temp=arrays[j];
arrays[j]=arrays[j+1];
arrays[j+1]=temp;
}
}
}
System.out.println("比较次数:" + count);
}
运行结果
稀疏数组
需求提出,在五子棋或者围棋游戏中涉及到存档问题,可以使用数组进行存储,但是如果棋面上只有几颗棋,那么数组中存储的很多值都是0,可以说存储了许多没有意义的数据
解决方法
稀疏数组
- 当一个数组中大部分元素为0,或者为同一数值时,可以使用私塾数组来保存该数组
- 稀疏数组的处理方式为:
- 记录数组有几行几列,有多少个不同的值
- 把具有不同值的元素和行列以及值记录到一个小规模的数组中
如图所示:
public static void main(String[] args) {
//创建二位数组11*11,0:没有棋子 1:黑棋 2:白棋
int[][] nums = new int[11][11];
nums[1][2] = 1;
nums[2][3] = 2;
System.out.println("输出原始数据");
for (int[] num : nums) {
System.out.println(Arrays.toString(num));
}
System.out.println("转换为稀疏数组");
//1.获取有效值的个数
int sum =0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (nums[i][j]!=0)
sum++;
}
}
System.out.println("有效值的个数为:" + sum);
//2.创建稀疏数组,行固定为有效值个数+1,列固定为3列
int[][] array = new int[sum + 1][3];
array[0][0] = 11;
array[0][1] = 11;
array[0][2] = sum;
//遍历二维数组,将非零元素,放入稀疏数组中
int count = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums[i].length; j++) {
if(nums[i][j] != 0)
{
array[count][0] =i;
array[count][1] =j;
array[count][2] =nums[i][j];
count++;
}
}
}
//输出稀疏数组
System.out.println("输出稀疏数组");
for (int[] ary : array) {
System.out.println(Arrays.toString(ary));
}
System.out.println("还原");
int[][] trans = new int[array[0][0]][array[0][1]];
for (int i = 1; i <= array[0][2]; i++) {
trans[array[i][0]][array[i][1]] =array[i][2];
}
System.out.println("输出还原后的数组");
for (int[] tra : trans) {
System.out.println(Arrays.toString(tra));
}
}
运行结果