文章目录
一维数组
- java语言中的数组是一种引用数据类型,不属于基本数据类型,父类是Object
- 数组实际上相当于一个容器,可以同时存储多个元素
- 数组当中可以存储“基本数据类型”,也可以存储“引用数据类型”的数据
- 数组是引用数据类型,所以数组对象在堆内存当中存储。如果数组当中存储的是java对象的话,实际上存储的是对象的引用(内存地址)
- 数组一旦创建,java规定,长度不再改变。
- 数组的分类:一维数组、二维数组、三维数组、多维数组
- 每个数组对象都有length属性,用于获取数组中元素的个数。数组每个元素都是有下标的,以0开始,以1递增,最后一个元素为length-1。对于元素的存取操作都需要通过下标来进行操作
- java要求数组中元素的类型统一,int类型数组只能存储int类型
- 数组存储的特点:数组中的元素的内存地址的连续的,数组中首元素的内存地址,作为整个数组的内存地址。
- 优点:查询检索某个下标的元素时,效率极高
- 每一个元素的内存地址在空间存储上都是连续的
- 每一个元素类型相同,所以占用空间大小一致
- 知道第一个元素的内存地址,知道每一个元素占用的空间大小,知道所求的下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址,直接通过内存地址定位元素。
- 缺点
- 由于数组中内存地址是连续的,进行增删数组元素的时候【除最后一个元素】,需要将之后的所有元素向前或者向后移动
- 数组不能存储大量数据,因为很难在内存空间上找到一块特别大的连续的内存空间。
数组java
-
声明一维数组
- int[] array;
- double[] array;
- boolean[] array;
- String[] array;
- Object[] array;
-
初始化一维数组
- 静态初始化
- int[] arry ={100,20,30,40,50}
- 动态初始化【先开空间】 ——例题一
- int[] array=new int[5];//5代表数组的元素个数,初始化一个5个长度的int类型的数组,每个元素默认值为0
- 静态初始化
-
当一个方法的参数是一个数组的时候,进行传参——见例二
数组基础操作
package datastructure.array;
public class ArrayTest01 {
public static void main(String[] args) {
int[] a1= {1,2,3,4,4,6,7,8};
//下标0 1 2 3 4 5 6 7
//所有数组对象都有length属性!!属性!!!
System.out.println("a1数组中元素的个数"+a1.length);
//利用下标对元素进行读取操作
System.out.println("第一个元素"+a1[0]);
System.out.println("最后一个元素"+a1[a1.length-1]);
//利用数组下标对元素进行修改操作
a1[0]=110;
a1[a1.length-1]=120;
//数组遍历
for(int i =0;i<a1.length;i++) {
System.out.print(a1[i]+"\t");
}
System.out.println();
//下标越界 异常 ArrayIndexOutOfBoundsException
//System.out.println(a1[10]);
//倒序遍历
for(int i =a1.length-1 ;i>=0;i--) { //最大下标数:a1.length-1
System.out.print(a1[i]+"\t");
}
}
}
例题一
package datastructure.array;
public class ArrayTest02 {
public static void main(String[] args) {
int[] a = new int[4];
//动态方式创建Object类型数组
Object[] objs =new Object[3]; //引用数据类型默认值为null
for(int i = 0;i<objs.length;i++) {
System.out.print(objs[i]+"\t");
}
}
}
例题二
package datastructure.array;
/**
* @author 衣鱼
* 当方法上一个参数的类型 是数组的时候
*
*/
public class ArrayTest02 {
public static void main(String[] args) {
//调用方法时传一个数组
int[] x1 = {0,1,2,3};
printArray(x1);
//动态初始化
int[] x2=new int[4];
printArray(x2);
printArray(new int[3]);
}
//打印数组元素printArray()
public static void printArray(int[] array) {
for(int i = 0;i<array.length;i++) {
System.out.print(array[i]+"\t");
}
System.out.println();
}
}
main: String[] args
- String[] args数组主要是用来接收用户的输入参数的。
控制台输入abc sdf 12j,那么jvm自动将abc sdf 12j以空格的方式进行分离,分离完成之后,自动放到String[] args数组当中。即{“abc”,“sdf”,“12j”} - 模拟一个系统,假设这个系统需要输入用户名和密码才能使用
- 运行代码时,接收用户输入设置,如图所示,在arguments栏中的program argument框中输入需要传入的参数。
- 运行代码时,接收用户输入设置,如图所示,在arguments栏中的program argument框中输入需要传入的参数。
例题三
package datastructure.array;
/**
* @author 衣鱼
* main 方法详解
* 模拟一个系统,假设这个系统需要输入用户名和密码才能使用
*/
public class ArrayTest03 {
/*//mian方法是jvm负责调用,jvm调用的时候一定会传一个String的数组
public static void main(String[] args) {
//jvm默认传递过来的数组长度默认是0
System.out.println("jvm传递的String数组参数长度为"+args.length);
//String[] args 什么时候会有值呢? 用户在控制台输入参数,这个参数自动会被转换为String[] args
}
*/
//用户名和密码输入String[] args数组当中
public static void main(String[] args) {
if(args.length!=2) {
System.out.println("使用该系统时,请输入程序参数,参数中包括用户名和密码信息.例如:bob 123");
return;
}
//程序执行到此说明用户确实提供用户名和密码
//之后需要判断用户名和密码是否正确
//取出用户名
String username = args[0];
//取出密码
String password = args[1];
//判断用户名和密码是否匹配
//if(username.equals("衣鱼")&&password.equals("2580")) { //容易空指针异常 username为null
if("衣鱼".equals(username)&&"2580".equals(password)) { //即使输入的字符串为空,也不会空指针异常
System.out.println("登录成功!欢迎"+username+"回来");
System.out.println("系统正为您更新");
}
else {
System.out.println("您输入的密码错误,请检查密码!或者该用户不存在!");
}
}
}
一维数组:存储引用类型元素
- 数组的存储类型:引用数据类型
- 数组中存储的元素是引用,是java对象的内存地址。
- 存放父类型的数组,可以存放子类型数据 Animal Cat Brid
- 数组取出的元素可能是cat,也可能是brid。但是调用的方法都是父类共有的,属于animal,不需要向下转型
- 如果想调用子对象特有方法,需要向下转型。
例题四
package datastructure.array;
/**
* @author 衣鱼
* 一维数组的深入
* 数组的存储类型:引用数据类型
* 数组中存储的元素是引用,是java对象的内存地址。
*/
public class ArrayTest04 {
public static void main(String[] args) {
//创建animal类型的数组
Animal a1= new Animal();
Animal a2= new Animal();
Animal[] animals= {a1,a2};
//遍历
for(int i =0;i<animals.length;i++) {
//Animal a = animals[i];
//a.move();
animals[i].move(); //代码合并
}
//修改
//Animal数组中只能存放Animal类型,不能存放product类型
//animals[1]=new Product();
animals[1]=new Cat(); //存放父类型的数组,可以存放子类型数据
//查看
Animal[] ani = {new Cat(),new Brid()};
for(int i = 0;i<ani.length;i++) {
//ani[i]取出的可能是cat,也可能是brid。但是调用的方法都是父类共有的,属于animal,不需要向下转型
Animal b = ani[i];
b.move();
//如果想调用子对象特有方法,需要向下转型。
if(ani[i] instanceof Cat) { //ani[i]是Cat类的一个实例吗
Cat c = (Cat)ani[i];
c.catchMouse();
}
else if(ani[i] instanceof Brid) {
Brid d =(Brid)ani[i];
d.sing();
}
}
}
}
class Animal {
public void move() {
System.out.println("Animal move!!");
}
}
class Product{
}
class Cat extends Animal{
public void move () {
System.out.println("cat move!");
}
//猫特有方法
public void catchMouse(){
System.out.println("cat catch mouse!");
}
}
class Brid extends Animal{
public void move() {
System.out.println("brid fly!");
}
//鸟特有方法
public void sing() {
System.out.println("brid sing !");
}
}
数组扩容
- 数组的扩容:在java开发中,数组的长度一旦确定是不可变的,数组满了,就需要扩容
- 扩容思路:新建一个大容量的数组,然后将小容量的数组中的数据逐个拷贝到大容量数组当中。【套娃】
结论:数组的扩容效率低,涉及到拷贝问题,这就需要开发人员预估计数组的大小。
例题五
package datastructure.array;
/**
* @author 衣鱼
* 数组的扩容:在java开发中,数组的长度一旦确定是不可变的,数组满了,就需要扩容
* 扩容思路:新建一个大容量的数组,然后将小容量的数组中的数据逐个拷贝到大容量数组当中。【套娃】
* 结论:数组的扩容效率低,涉及到拷贝问题,这就需要开发人员预估计数组的大小。
*/
public class ArrayTest05 {
public static void main(String[] args) {
//java中数组的拷贝工作
int[] src = {1,2,3,4,5,6};
int[] dest =new int[10];
//将src的3,4,5复制到dest下标从4开始
System.arraycopy(src, 2, dest, 4,3);
//遍历数组
for(int i =0;i<dest.length ;i++) {
System.out.println(dest[i]);
}
//数组:引用数据类型扩容
Object[] objs = {new Object(),new Object(),new Object()};
Object[] destobjs= new Object[5];
System.arraycopy(objs, 0, destobjs,0, objs.length);
for(int i =0;i<destobjs.length ;i++) {
System.out.println(destobjs[i]);
}
}
}
二维数组
- 二维数组实际上是一种特殊的一维数组,这个特殊的一维数组当中的每一个元素都是一个一维数组
package datastructure.array;
/**
* @author 衣鱼
* 二维数组
*
*/
public class ArrayTest06 {
public static void main(String[] args) {
//一维数组
int[] array1 = {1,2,3,4};
//二维数组
int[][] array2 = {{},{},{}}; //每个元素都是特殊的一维数组
//二维数组静态初始化
int[][] array3 = { //三个一维数组
{11,12,13,14},
{21,22,23,24,25},
{31,32,33,34,35,36}
};
System.out.println(array3.length); //二维数组array3的长度为3
System.out.println(array3[0].length); //array3[0]一维数组长度为4
System.out.println("======================");
//二维数组动态初始化
//理解[][] 两个中括号代表意义
int[][] array4 = new int[2][3];
System.out.println(array4.length); //2 有几个一维数组
System.out.println(array4[1].length); //3 第X个一维数组中的长度
//两行三列,有两个一维数组,每个一维数组有三个元素
//取出array3第2个一维数组的第3个元素 ——23
System.out.println("array3第2个一维数组的第3个元素是"+array3[1][2]);
System.out.println("======================");
//遍历二维数组
for(int i =0 ;i<array3.length;i++) {
for(int j =0;j<array3[i].length;j++) {
System.out.print(array3[i][j]+"\t");
}
System.out.println();
}
//利用方法遍历
printArray(array4);
}
//方法:遍历二维数组
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]+"\t");
}
System.out.println();
}
}
}
算法
冒泡排序算法
package datastructure.array;
/**
* @author 衣鱼
* 原序列:9,6,5,2,8,3
* 第一次排序 第一个位置的数:9 利用9排除最大泡
* 9,6,5,2,8,3
* 6,9,5,2,8,3
* 6,5,9,2,8,3
* 6,5,2,9,8,3
* 6,5,2,8,9,3
* 6,5,2,8,3,9
*
*第二次排序 第一个位置的数:6 利用6排出余下的最大泡
* 5,6,2,8,3
* 5,2,6,8,3
* 5,2,6,8,3 [6,8不需要交换]
* 5,2,6,3,8
*
*第三次排序 第一个位置的数:5 利用5排出余下的最大泡
* 2,5,6,3
* 2,5,6,3
* 2,5,3,6
*
*第四次排序 第一个位置的数:2 利用2排出余下的最大泡
* 2,5,3
* 2,3,5
*
*第五次排序 第一个位置的数:2 利用2排出余下的最大泡
* 2,3
*
*/
public class BubbleSort {
public static void main(String[] args) {
int[] arr = {9,6,5,2,8,3,7,10,5,6,1};
//冒泡排序
//从左向右,依次比较,大数在右
for(int i= arr.length-1;i>0;i--) {
for(int j =0;j<i;j++) {
if(arr[j]>arr[j+1]) {
int x =arr[j]; //临时变量
arr[j]=arr[j+1];
arr[j+1]=x;
}
}
}
PrintArray(arr);
}
//遍历函数
public static void PrintArray(int[] array) {
for(int i =0;i<array.length;i++) {
System.out.print(array[i]+"\t");
}
System.out.println();
}
}
选择排序算法
package datastructure.array;
/**
* @author 衣鱼
* 选择排序
* 每次从这堆参与比较的数据中找出最小值
* 将最小值和[参与比较的数据中]最前面的元素交换位置
* 选择排序相比于冒泡排序的优点:每一次交换的位置都是有意义的。
* 给学生按高矮排队,找出来班里面最矮的A,与第一个位置的同学交换位置。
* 此时已经给A排好位置,A不属于待排集合里面,在剩下的同学里面,找出来最矮的同学,与待排集合的第一个位置的同学交换位置
* 以此类推 n个同学,比较n-1次
*/
public class SelectSort {
public static void main(String[] args) {
int[] arr = {5,6,2,3,1,54,82,64,7,52,34,95};
for(int i = 0;i<arr.length;i++) {
for(int j =i+1;j<arr.length;j++) {
//默认第i个下标最小
if(arr[i]>arr[j]) {
int temp =arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
PrintArray(arr);
}
//遍历函数
public static void PrintArray(int[] array) {
for(int i =0;i<array.length;i++) {
System.out.print(array[i]+"\t");
}
System.out.println();
}
}
二分法查找
package datastructure.array;
import java.util.Arrays;
/**
* @author 衣鱼
* 查找数组内元素
* 线性查找
* 二分法查找
* 二分法查找基于排序的基础之上
* 二分法查找效率要高于线性查找
*
*例:
* 数组元素 20 30 40 50 60 70 80 90 100 110
* 数组下标 0 1 2 3 4 5 6 7 8 9
* 查找元素 70
* ①首尾下标相加除以2,取整,得到中间下标 (0+9)/2 =4
* ②找到下标为4的元素 60 ,比较60与待查找数据,60<70,说明70在60的右侧 ——要求有序
* ③首尾下标相加除以2,取整,得到中间下标 【首变成中间下标+1: 4+1=5】(5+9)/2=7
* ④找到下标为7的元素 90 ,比较90与待查找数据,90>70,说明70在90的左侧
* ⑤首尾下标相加除以2,取整,得到中间下标 【尾变成中间下标-1】(5+6)/2 =5
* ⑥找到70,返回数组下标
*/
public class ArraySearch {
public static void main(String[] args) {
int[] arr = {5,6,28,54,82,827,828,219,16,817,71,17,85};
//arraySearch(arr,16);
//排序
Arrays.sort(arr);
//有序遍历
PrintArray(arr);
//二分法查找
binarySearch(arr,16);
System.out.println(binarySearch(arr,16));
}
/**二分法查找
* */
private static int binarySearch(int[] arr, int dest) {
int begin =0;
int end =arr.length-1;
while(begin<=end) { //难点:开始元素在结束元素的左侧就有机会继续循环!
int mid =(begin+end)/2;
if(arr[mid]==dest) {
return mid;
}else if(arr[mid]<dest) {
//目标数据在中间数据在右侧
begin=mid+1;
}else{
//(arr[mid]>dest)
//目标数据在中间数据的左侧
end =mid-1;
}
}
return -1;
}
/**
* 线性查找数组内元素
* array 被查找的数组
* a 被查找的元素
* return i 返回匹配的元素的数组下标
* return -1 该数组没有该元素
* */
public static int arraySearch(int[] array,int a) {
for(int i = 0;i<array.length;i++) {
if(array[i]==a) {
return i;
}
//return -1; //注意循环!
}
return -1;
}
//遍历函数
public static void PrintArray(int[] array) {
for(int i =0;i<array.length;i++) {
System.out.print(array[i]+"\t");
}
System.out.println();
}
}
Arrays工具类
- Arrays类包含用来操作数组(比如排序和搜索)的各种方法
- 二分法搜索,适用以下类型
- static int
binarySearch(int[] a, int fromIndex, int toIndex, int key)
使用二分搜索法来搜索指定的 int 型数组的范围,以获得指定的值。 - static boolean
equals(char[] a, char[] a2)
如果两个指定的 char 型数组彼此相等,则返回 true。 - static void
fill(int[] a, int val)
将指定的 int 值分配给指定 int 型数组的每个元素。- static void
fill(int[] a, int fromIndex, int toIndex, int val)
将指定的 int 值分配给指定 int 型数组指定范围中的每个元素。
- static void
- static int
hashCode(double[] a)
基于指定数组的内容返回哈希码。 - static void
sort(long[] a, int fromIndex, int toIndex)
对指定 long 型数组的指定范围按数字升序进行排序。
package datastructure.array;
import java.util.Arrays;
/**
* @author 衣鱼
* java.util.Arrays; 工具类有很多方法,开发时可参考API的帮助文档
*/
public class ArraysTest02 {
public static void main(String[] args) {
int[] arr = {5,28,2,592,329,82,55,15,816,6,73,10,768};
Arrays.sort(arr);
//遍历
for(int i = 0;i<arr.length;i++) {
System.out.print(arr[i]+"\t");
}
System.out.println();
//二分法查找
int index =Arrays.binarySearch(arr, 768);
System.out.println(index==-1?"该元素不存在":"该元素的下标为"+index);
}
}