Java数组的使用和定义

  数组 就是指一组相关类型的变量集合,并且这些变量可以按照统一的方式进行操作。

1.数组的基本用法

   1.1创建数组

  数组是引用类型,在Java当中所有引用类型想要分配空间就必须要使用new关键字。

  • 数组静态初始化
	数据类型[] 数组名称 = {初始化数据};
	 int[] array1 = {1,2,3,4,5,6};

  静态初始化时候,数组元素的个数和初始化数据的格式是保持一致的。

  • 数组动态初始化(声明并开辟数组)
	数据类型[] 数组名称 = new 数据类型[长度]int[] array2 = new int[]{1,2,3,4,5};
	int[] array3 = new int[5];

  数组3未进行初始化,若数组的数据类型为引用类型时,数据初始值为null;若数组的数据类型为基本数据类型时,数据初始值为0。上述的array3的数据初始值即为0。

  1.2数组的使用

  在Java当中有一种能够动态获取数组长度的方法:数组名称.length ,这是一个属性而不是一个方法

  • 获取长度并访问数组的元素
	int[] array = {1,2,3,4,5};
	System.out.println("数组的长度为:"+array.length);
	System.out.println(array[1]);
	System.out.println(array[3]);
	array[2] = 99;
	System.out.println(array[2]);
	----------------------------------------
	输出结果:
	数组的长度为:5
	2
  	4
  	99

  注意事项:
   1. 使用 [ ] 按下标访问数组元素的时候,是从0号下标进行计数的。
   2. 下标的访问不要超出了数组的有效范围 [0,length-1],若超出了这个有效范围就会发生下标越界异常(java.lang.ArrayIndexOutofBoundsExecption

     示例1:

	int[] array = new int[]{1,2,3,4,5};
	System.out.println(arr[66]);
	----------------------------------------------------
	执行结果:
		Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:66
		at JavaTest10.main

     示例2:使用for-each遍历数组

	int[] array = new int[]{1,2,3,4,5,6}
	for(int x: array){
		System.out.print(x+" ");
	}
	------------------------------------------------
	输出结果:
		1 2 3 4 5 6

2.数组作为方法的参数

   2.1基本用法

   示例:将数组所有元素相加返回和。

	public static void addArray(int[] array){
		int sum = 0;
		for(int x: array){
			sum += x;
		}
		return sum;
	}
	public static void main(String[] args){
		int[] array = {1,2,3}
		System.out.println(addArray(array));
	}
	-------------------------------
	输出结果:
	6
   2.2 引用类型

  示例1:将基本数据类型作为参数传入方法当中。

public static void func(int n){
	n = 100;
	System.out.println("n = "+n);
}
public static void main(String[] args){
	int num = 10;
	func(num);
	System.out.println("num = "+num);
}
---------------------------------
输出结果:
n = 100
num = 10

  在上述的代码当中,修改形参的值并没有改变实参的值。

  示例2:将数组(引用)类型作为参数传入方法当中。

public static void func(int[] n){
 n[0] = 100;
 System.out.println("n[0] = "+n[0]);
}
public static void main(String[] args){
 int[] num = {10};
 func(num);
 System.out.println("num[0] = "+num[0]);
}
----------------------------------
输出结果:
n[0] = 100
num[0] = 100

  通过上述示例1 和示例2可以得知在方法内部修改了数组的内容,方法内部也会发生改变。数组是引用类型,数组名num在本质上只是存放了数组起始内存的地址。

   2.3 初识JVM内存区域的划分

   .java文件通过编译之后会生成 .class(字节码文件),通过加载到JVM实现代码的功能。
  JVM 的内存大致被分为几个区域,如下图所示:
在这里插入图片描述

  • 程序计数器(PC Register):很小的一块空间,保存下一条执行指令的地址。
  • 虚拟机栈(JVM Stack):存储了局部变量表 以及其他一些信息。
  • 本地方法栈(Native Method Stack):本地方法栈和虚拟机栈的作用类似,只不过保存的是Native方法的局部变量。
  • 堆(Heap):JVM所管理的最大内存区域,使用new 创建的对象都是在堆上保存的。
  • 方法区(Method Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器后的字节码等数据。
  • 运行时常量池(Runtime Constant Pool):是方法区的一部分,存放字面量与符号引用。
        对于常量池来说,在JDK1.7之前,常量池是放在方法区当中的;
                   在JDK1.7开始,常量池在堆中。

        示例:
	String str1 = "hello";
   	String str2 = "he" + new String("llo");
	System.out.println(str1 == str2);
	System.out.println(str1.equals(str2));
   	 -------------------------------------------------
	输出结果:
	false
   	true

    分析:String str1 = “hello”; 这样创建字符串是存在于常量池当中的;
       String str2 = new String(“llo”); str2存在于堆当中;
       “ == ” 是为了验证两个对象是否为一个(内存的地址是否相同);
       str1.equals(str2) 仅仅只是比较二者之间的内容是否相同。
    因此在实际情况下比较两个字符串的内容是否相同应该使用equals来判断。
  关于虚拟机栈还有堆还有如下几点需要注意:
    1. 局部变量和引用都保存在栈上,new出的对象也保存在堆上。
    2. 堆的控件非常大,栈的空间比较小。
    3. 堆是整个JVM共享一个,而栈每个线程都至少具有一份。

3.数组应用

   3.1 遍历数组
  • 使用for循环
  • 使用for - each遍历
  • 使用Array.toString(数组名)以字符串的形式输出数组
public static void myPrintOne(int[] array){
   for(int i = 0;i < array.length -1;i++){
       System.out.print(array[i]+" ");
   }
   System.out.println();
}
public static void myPrintTwo(int[] array){
   for(int x: array){
       System.out.print(x + " ");
   }
   System.out.println();
}
public static void main(String[] args) {
   int[] array = new int[]{1,2,3,4,5,6,7,8,9,10};
   myPrintOne(array);
   myPrintTwo(array);
   System.out.println(Arrays.toString(array));
}
---------------------------------------
输出结果:
1 2 3 4 5 6 7 8 9 
1 2 3 4 5 6 7 8 9 10 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
   3.2 拷贝数组
  • System.arraycopy()
  • Arrays.copyOf()
  • 模拟实现Arrays.copyOf()
  • array.clone()
public static void myPrintOne(int[] array){
   for(int i = 0;i < array.length -1;i++){
       System.out.print(array[i]+" ");
   }
   System.out.println();
}
public static void myPrintTwo(int[] array){
   for(int x: array){
       System.out.print(x + " ");
   }
   System.out.println();
}
public static int[] myCopyOf(int[] array,int length){
       int[] ret = new int[length];
       for (int i = 0; i < length; i++) {
           ret[i] = array[i];
       }
       return ret;
}
public static void main(String[] args) {
   int[] array = new int[]{1,2,3,4,5,6,7,8,9,10};
   int[] ret = new int[array.length];
   System.arraycopy(array,0,ret,0,array.length);
   System.out.println("System.arraycopy()拷贝的结果为: "+Arrays.toString(ret));
   ret =Arrays.copyOf(array,array.length);
   System.out.println("Arrays.copyOf()拷贝的结果为: "+Arrays.toString(ret));
   ret = myCopyOf(array,array.length);
   System.out.println("myCopyOf()拷贝的结果为: "+Arrays.toString(ret));
   System.out.println("array.clone()拷贝的结果为: "+Arrays.toString(array.clone()));
}
------------------------------------------------------------------------------------------------
输出结果:
System.arraycopy()拷贝的结果为: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Arrays.copyOf()拷贝的结果为: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
myCopyOf()拷贝的结果为: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
array.clone()拷贝的结果为: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

   System.arraycopy()和 Array.copyOf()的区别与联系:
    Array.copyOf()方法调用了System.arraycopy(),在速度上略低一筹;
    System.arraycopy()被 native所修饰,处理速度很快。
   相比于赋值语句,Array.copyOf()是将数组进行深拷贝,即使修改原数组也不会影响到新数组。而浅拷贝如果是两个引用同时指向同一个对象,那么通过一个引用修改当前对象的值后,那么另一个对象引用也会受到影响,这样的拷贝即为浅拷贝)与其反之。

   3.3 二分查找

    递归方式:

public static int binarySearch(int[] array,int key,int left,int right) {
    if (left <= right) {
        int mid = (left + right) / 2;
        if (array[mid] == key) {
            return mid;
        } else if (array[mid] < key) {
            return binarySearch(array, key, mid + 1, right);
        } else {
            return binarySearch(array, key, left, mid - 1);
        }
    }
    return -1;
}

    非递归方式:

public static int binarySearch(int[] array,int key){
    int left = 0;
    int right = array.length - 1;
    while(left <= right){
        int mid = (left + right) >>> 1;
        if(array[mid] < key){
            left = mid + 1;
        }else if (array[mid] > key){
            right = mid - 1;
        }else {
            return mid;
        }
    }
    return -1;
}

4.二维数组

   二维数组其本质上也是一维数组,只不过每一个元素又是一个一维数组。
   基本语法

数据类型[][] 数组名称 = new 数据类型[行数][列数]{初始化数据};

   打印二维数组可以使用Arrays.deepToString(数组名称)

public static void main(String[] args) {
    int[][] array4 = new int[3][];
    array4[0] = new int[3];
    array4[1] = new int[4];
    array4[2] = new int[5];            
    System.out.println(Arrays.deepToString(array4));
}
---------------------------------------
输出结果:
[[0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0, 0]]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值