JavaSE进阶 数组
2021/4/27 12:25:24
本文主要是介绍JavaSE进阶 数组,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一维数组
概述
- Java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object。
- 数组实际上是一个容器,可以同时容纳多个元素(数组是数据的集合)
- 元素的类型要统一
- 数组中的元素内存地址是连续的
- 数组中可以存储“基本数据类型”和“引用数据类型”(对象的引用,即内存地址,4个字节长度)的数据
- 因为数组是引用数据类型,所以数组对象是在堆内存当中(数组存储在堆内存当中)
- 数组一旦创建,在java中规定,长度不可变(数组长度不可变)
- 所有数组对象都有length属性(java自带的),用来获取数组中的元素个数
- 数组是一种数据结构
- 所有数组都是将首元素的内存地址作为自己的内存地址
- 数组中的每一个元素都有下标,下标从0开始,以1递增,最后一个元素的下标是:length-1
特点总结:连续、统一、不变
内存结构图
优点
- 每一个元素的内存地址在空间储存上是连续的
- 每一个元素类型相同,所以占用空间大小一样
- 知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率是最髙的。
数組中存储100个元素,或者存储100万个元素,在元素査询/检索方面,效率是相同的,因为数組中元素査找的肘候不会一个一个找,是通过数学表达式计算出来的。
缺点
- 由于为了保证数组中每个元素的内存地址连续,所以在数纽上随机删除或者増加元素的时候,效率较低,因为随机増删元素会涉及到后面元素统一向前或者向后位移的操作。
- 数组不能存储大數据量,因为很难在内存空间上找到一块特别大的连续的内存空闾。
注意:对于数组中最后一个元素的増删,是没有效率形响的。
声明/定义
Java风格 int[] array01; c++的方式,不建议 int array01[]; eg.main方法中的参数 String[] args或者 String args[]
初始化
静态初始化
int[] array01={1,2,3,4,5};
动态初始化
int[] array01=new int[5]; 每个元素默认值是0 String[] array02=new String[5]; 每个元素默认值是null
当你创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式,不确定的时候,采用动态初始化,预先分配内存空间
遍历数组
int[] a={1,2,3,4,5}; //从第一个元素开始遍历 for(int i=0;i<a.length;i++){ System.out.println(a[i]); } //从最后一个开始遍历 for(int i=a.length-1;i>=0;i--){ System.out.println(a[i]); }
方法参数是数组
public class ArraysTest01 { public static void main(String[] args) { int[] a={1,2,3}; printArray(a); System.out.println("-------------"); printArray(new int[3]); System.out.println("-------------"); printArray(new int[]{6,7,8}); } public static void printArray(int[] array){ for(int i=0;i<array.length;i++){ System.out.println(array[i]); } } }
结果:
解析mian方法参数
“String[ ] args”有什么作用?JVM调用main方法时,会自动传一个String数组过来,主要用来接收用户输入参数的。
这个数组什么时候里面会有值呢?其实这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动会披转换为"String[ ] args" 。例如这样运行程序∶java ArrayTest05 abc def xyz,那么这个时候JVM会自动将abc def xyz通过空格的方式进行分离,分离完成之后,自动放到“String[ ] args”数组。(把abc def xyz转换成字符串数组:{“abc”,“def”,“xyz”})
public class ArraysTest02 { public static void main(String[] args) { //这里测试得出两个结论 //1.args数组长度默认值为0 //2.args不为null,可能JVM内部已进行初始化 System.out.println("args数组长度为"+args.length); String[] strs={ }; printLength(strs); for(int i=0;i< args.length;i++){ System.out.println(args[i]); } } public static void printLength(String[] array){ System.out.println("strs数组长度为"+array.length); } }
怎么在IDEA中传入abc、def、xyz等参数? run→edit configuration→在Program arguments上打上abc、edf、xyz,结果如下:
实际应用:模拟一个系统,假设这个系统要使用,必须输入用户名和密码
public class ArrayTest03 { public static void main(String[] args) { if(args.length!=2){ System.out.println("要使用此系统,必须输入用户名和密码,如 zhangsan 123"); return; } //程序执行到这里说明正确输入了信息 //取出用户名 String username=args[0]; //取出密码 String password=args[1]; //表示用户名为admin,密码是123时登录成功,其他一律失败 //username.equals("admin")&&password.equals("123") //以下写法能避免空指针异常 if("admin".equals(username)&&"123".equals(password)){ System.out.println("登录成功,欢迎["+username+"]回来"); System.out.println("您可以继续使用该系统...."); }else{ System.out.println("验证失败,用户名不存在或者密码错误!"); } } }
存储引用数据类型
public class ArraysTest04 { public static void main(String[] args) { Bird a1=new Bird(); Cat a2=new Cat(); Plant a3=new Plant(); //能放子类,放不了Plant类 Animal[] ans= {a1,a2}; //Animal中没有Scratch()方法 //ans[0].Scratch(); for(int i=0;i< ans.length;i++){ if(ans[i] instanceof Cat){ Cat cat=(Cat)ans[i]; cat.scratch(); }else if(ans[i] instanceof Bird){ Bird bird=(Bird)ans[i]; bird.sing(); } } } } class Animal{ public void move(){ System.out.println("Animal is moving."); } } class Cat extends Animal{ @Override public void move() { System.out.println("Cat is walking"); } public void scratch(){ System.out.println("疯狂乱抓"); } } class Bird extends Animal{ @Override public void move() { System.out.println("Bird is flying."); } public void sing(){ System.out.println("Bird is sing songs."); } } class Plant{ public void absorb(){ System.out.println("Plant is obsorbing CO2"); } }
数组扩容
在java开发中,数组长度一旦确定不可变,那么数组满了时需要扩容。 java中对数组的扩容是∶先新建—个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。
结论:数组扩容效率较低。印为涉及到拷贝的问题。所以在以后的开发中请注章∶尽可能少的进行数组的拷贝。可以在创建数组对象的时候预估计一下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。
public class ArraysTest05 { public static void main(String[] args) { //数组拷贝 //拷贝源 int[] src={1,11,22,3,4}; //拷贝目标 int[] dest=new int[20];//动态初始化,每个元素默认值为0 //调用JVM System类中的arraycopy方法,来完成数组的拷贝 System.arraycopy(src,1,dest,3,2); for(int i=0;i< dest.length;i++){ System.out.println(dest[i]); //0 0 0 11 22 ... 0 } //完全拷贝 System.arraycopy(src,0,dest,0,src.length); Object[] obj={new Object(),new Object(),new Object()}; Object[] newObj=new Object[5]; //这里拷贝的是对象的地址,而不是对象 System.arraycopy(obj,0,newObj,0,obj.length); for(int i=0;i< newObj.length;i++){ System.out.println(newObj[i]); //java.lang.Object@16b98e56 java.lang.Object@7ef20235 java.lang.Object@27d6c5e0...null } } }
二维数组
二维数组其实是一个特殊的一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组。三维数组是一个特殊的二维数组,特殊在这个二维数组中每一个元素是一个一维数组。
遍历
public class ArraysTest06 { public static void main(String[] args) { //静态初始化 int[][] a={ {1,2,3}, {4,5,6,7}, {8,9,10} }; System.out.println(a[2][2]); System.out.println("--------------------"); printArray(a); System.out.println("--------------------"); printArray(new int[][] { {11,22},{33,44,55} }); } public static void printArray(int[][] array){ for(int i=0;i<array.length;i++){ //负责纵向 for(int j=0;j<array[i].length;j++){ System.out.print(array[i][j]+" "); } System.out.println(); } } }
算法
冒泡排序算法
- 每一次循环结束之后,都要找出最大的数据,放到参与比较的这堆数据的最右边。(冒出最大的那个气泡)
- 左边和右边比大小,左边>右边时交换位置
/* 冒泡排序法: 原始数据:3 2 8 7 1 最外层循环4次 内层循环最大4次递减 第一次循环: 2 3 8 7 1(3比2,交换) 2 3 8 7 1(3比8,不交换) 2 3 7 8 1(8比7,交换) 2 3 7 1 8(8比1,交换) 第二次循环:2 3 7 1 2 3 7 1(2比3,不交换) 2 3 7 1(3比7,不交换) 2 3 1 7(7比1,交换) 第三次循环:2 3 1 2 3 1(2比3,不交换) 2 1 3(3比1,交换) 第四次循环:2 1 1 2(2比1,交换) */ public class BubbleSort { public static void main(String[] args) { int[] a={3 ,2 ,8 ,7 ,1}; //5个数据,循环4次 //for(int i=0;i<a.length-1;i++){} //定义一个比较次数 int count=0; //采用递减的方式与内层循环有联系 for(int i=a.length-1;i>0;i--){ for(int j=0;j<i;j++){ count++; if(a[j]>a[j+1]){ int temp; temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } //比较次数 System.out.println("比较次数:"+count); //输出结果 for(int i=0;i<a.length;i++){ System.out.println(a[i]); } } }
选择排序算法
每一次从这堆参与比较的数据当中找出最小值,拿着这个最小值和最前面的元素交换位置,选择排序比冒泡排序好在:每一次交换位置都是有意义的。关键点在于找出最小,先假设一开始最左边最小,假设
- 第一个3最小,3和2比,发现2更小,所以此时最小的是2
- 继续拿着2往下比对,2和6比较,2仍然是最小的
- 继续拿着2往下比对,2和1比较,发现1更小,所以此时最小的是1
- 继续拿着1往下比对,1和5比较,1仍然是最小
与冒泡排序算法相比:比较次数一样、交换次数减少
/* 第一次循环:参与 3 1 6 2 5 (参与比较的最左边的元素下标为0) 1 3 6 2 5(排序后) 第二次循环:参与 3 6 2 5(参与比较的最左边的元素下标为1) 2 6 3 5(排序后) 第三次循环: 参与 3 6 5(参与比较的最左边的元素下标为2) 3 6 5(排序后) 第四次循环:参与 6 5(参与比较的最左边的元素下标为3) 5 6(排序后) 5条数据,循环4次 */ public class SelectSort { public static void main(String[] args) { int[] a={3,1,6,2,5}; int count=0; for(int i=0;i<a.length-1;i++){ //这时输出i正好是0 1 2 3 对应着起点下标 //假设起点i下标位置上的元素是最小的 int min=i; for(int j=i+1;j<a.length;j++){ count++; //输出j 对应i=0时 j为1 2 3 4 if(a[j]<a[min]){ min=j; } } //当i和min相等,说明一开始的假设是对的 //如果不相等,说明有更小的元素,需要交换位置 if(min!=i){ int temp; temp=a[min]; a[min]=a[i]; a[i]=temp; } } //比较次数 System.out.println("比较次数:"+count); //排序之后遍历 for(int k=0;k<a.length;k++){ System.out.println(a[k]); } } }
二分法查找
线性查找
//需求:找出89的下标,如果没有,返回-1 public class ArraySearch { public static void main(String[] args) { int[] a = {1, 6, 89, 55, 34}; int index = arraySearch(a, 55); System.out.println(index == -1 ? "该元素不存在" : "该元素下标是" + index); } //参数1:传入的数组 参数2:要找的元素值 //返回值返回下标,没有返回-1 public static int arraySearch(int[] array,int x){ for(int i=0;i<array.length;i++){ if(x==array[i]){ return i; } } return -1; } }
二分法查找(基于排序的基础上)
public class ArrayUtil { public static void main(String[] args) { int[] a = {1, 6, 11, 13, 17,19}; int index = binarySearch(a, 11); System.out.println(index == -1 ? "该元素不存在" : "该元素下标是" + index); } //参数1:传入的数组 参数2:目标元素 //返回值返回下标,没有返回-1 public static int binarySearch(int[] array,int dest){ //开始下标 int begin=0; //结束下标 int end=array.length-1; //开始元素的下标只要在结束元素下标的左边,就有机会循环 while (begin<=end){ //中间元素下标 int mid=(begin+end)/2; if (array[mid] == dest) { return mid; } else if (array[mid] < dest) { //到这里说明目标在中间的右边 begin = mid + 1; } else { //目标在中间的左边 end = mid - 1; } } return -1; } }
数组工具类
java.util.Arrays 工具类中的方法大多都是静态的,其中有sort( )方法和binarySort( ),可以排序。静态方法,直接使用类名调用就行。
public class ArraysTest08 { public static void main(String[] args) { int[] a={11,34,5,43,33,44}; //排序 Arrays.sort(a); //遍历 for(int i=0;i<a.length;i++){ System.out.print(a[i]+" "); } System.out.println(); //二分法查找 int index=Arrays.binarySearch(a,44); System.out.println(index==1?"该元素不存在":"该元素的下标是"+index); } }
这篇关于JavaSE进阶 数组的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28微服务架构中API版本控制的实践
- 2024-09-28AI给的和自己写的Python代码,都无法改变输入框的内容,替换也不行
- 2024-09-27Sentinel配置限流资料:新手入门教程
- 2024-09-27Sentinel配置限流资料详解
- 2024-09-27Sentinel限流资料:新手入门教程
- 2024-09-26Sentinel限流资料入门详解
- 2024-09-26Springboot框架资料:初学者入门教程
- 2024-09-26Springboot框架资料详解:新手入门教程
- 2024-09-26Springboot企业级开发资料:新手入门指南
- 2024-09-26SpringBoot企业级开发资料新手指南