Java中数组知识小结

一丶数组的基础知识

1. 什么是数组?

数组就是一个相同类型数据的集合,在内存上也是连续的。

2.数组的初始化

  • 静态初始化
    数据类型[ ] 数组名称 = {初始化数据}
    如:int[ ] array={1,2,3,4,5};
  • 动态初始化
    数据类型[ ] 数组名称 = new 数据类型 [ ] { 初始化数据 }
    如:int[ ] array=new int[ ] {1,2,3,4,5}
    或者不对数组进行初始化
    数据类型[ ] 数组名称 = new 数据类型 [ 数组长度]
    如:int[ ] array=new int[ 5];

3.访问数组中的元素

int int[] arr={1,2,3,4,5};
System.out.println(arr[1]);    // 执行结果: 2 
System.out.println(arr[0]);    //执行结果: 1 
arr[2] = 100; 
System.out.println(arr[2]);    //执行结果:100

从上面代码不难发现:

  • 使用 [ ] 按下标取数组元素时,下标从 0 开始
  • 使用 [ ] 操作既能读取数据, 也能修改数据

4.数组的长度问题

int[] arr = {1, 2, 3}; 
System.out.println(arr[100]);
// 执行结果 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100   
   at Test.main(Test.java4)

抛出了 java.lang.ArrayIndexOutOfBoundsException 异常. 使用数组一定要下标谨防越界.此外:

  • 使用 arr.length 能够获取到数组的长度,这个操作为成员访问操作符
  • 下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常

5.遍历一个数组

所谓 “遍历” 就是指将数组中的所有元素都访问一遍, 不重不漏. 通常需要搭配循环语句.

  • for循环遍历数组
int[] arr = {1, 2, 3}; 
for (int i = 0; i < arr.length; i++) {
    System.out.print(arr[i]+" "); 
}
// 执行结果 1 2 3
  • for-each 遍历数组
    for(表达式1:表达式2) 表达式1指数组中的变量,表达式2表示数组名
int[] arr = {1, 2, 3}; 
for (int x : arr) {    
	System.out.print(x); 
}
// 执行结果 1 2 3

for循环和for-each循环的的不同:
for-each循环不能用下标区访问

6.数组的拷贝

数组的拷贝:

  1. System.arrayCopy() (被native所修饰的方法,拷贝速度最快)
  2. for循环一个一个拷贝
  3. Arrays.copyOf() (调用了 System.arrayCopy() 速度慢)
  4. 数组名.clone() 数组名:拷贝的数组

以上四种拷贝方式,对数组当中如果是简单类型来说,那么就是深拷贝。如果数组存放的是引用类型,那么这四种方式就是浅拷贝。什么是浅拷贝呢?如果是两个引用,同时指向一个对象,那么通过一个引用,修改当前对象的值,那么另一个引用也会收到影响。这种拷贝就叫做浅拷贝。

7.数组的性质

public static void main(String[] args) {
	int num = 0;    
	func(num);    
	System.out.println("num = " + num); 
}
public static void func(int x) {    
	x = 10;    
	System.out.println("x = " + x); 
}
// 执行结果 
 x = 10
 num = 0 
public static void main(String[] args) {
	int[] arr = {1, 2, 3};     
	func(arr);     
	System.out.println("arr[0] = " + arr[0]); 
} 
public static void func(int[] a) {     
	a[0] = 10;     
	System.out.println("a[0] = " + a[0]); 
} 
 // 执行结果 
  a[0] = 10
  arr[0] = 10 

比较上面两段代码可以发现,前者修改形参 x 的值, 不影响实参的 num 值。
后者在函数内部修改数组内容, 函数外部也发生改变. 此时数组名 arr 是一个 “引用” . 当传参的时候, 是按照引用传参。

  • 什么是引用呢?
    引用相当于一个 “别名”, 也可以理解成一个指针.
    创建一个引用只是相当于创建了一个很小的变量, 这个变量保存了一个整数, 这个整数表示内存中的一个地址.
    比如后面一段代码中: int[ ] arr = new int[ ]{1, 2, 3} 内存布局如图:

当我们创建 new int[]{1, 2, 3} 的时候, 相当于创建了一块内存空间保存三个 int
在这里插入图片描述
接下来执行 int[] arr = new int[]{1, 2, 3} 相当于又创建了一个 int[] 变量, 这个变量是一个引用类型, 里 面只保存了一个整数(数组的起始内存地址)
在这里插入图片描述
接下来我们进行传参相当于 int[] a = arr , 内存布局如图
在这里插入图片描述
接下来我们修改 a[0] , 此时是根据 0x100 这样的地址找到对应的内存位置, 将值改成 100

在这里插入图片描述

此时已经将 0x100 地址的数据改成了 100 . 那么根据实参 arr 来获取数组内容 arr[0] , 本质上也是获取 0x100 地 址上的数据, 也是 100.
总结: 所谓的 “引用” 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实只 是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大).

扫描二维码关注公众号,回复: 9887238 查看本文章

8.Arrays工具类的使用

Arrays.copyOfRange();  //拷贝部分数组
Arrays.equals();       //比较两个数组是否相同,返回true或false
Arrays.fill();         //填充数组
Arrays.sort();      //对数组进行排序
Array.toString()     //将数组以字符串的方式打印
Array.deepToString()   //返回指定数组的“深度内容”的字符串表示形式

二丶二维数组

1.什么是二维数组
二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组。
2.基本语法
初始化方法与一位数组相似
数据类型[ ][ ] 数组名称={初始化数据}
如:int arr[ ][ ] arr={{1,2,3},{4,5,6}} ’
数据类型[ ][ ] 数组名称 = new 数据类型[ ][ ] { 初始化数据 }
如:int arr[ ][ ] arr=new int[ ][ ]{{1,2,3},{4,5,6}} ;
数据类型[ ][ ] 数组名称 = new 数据类型[ 数组长度][数组长度]
如:int [ ][ ] arr=new int[3 ][3 ];

  • 此外还有不规则的二位数组
    int [ ][ ] arr=new int[ 3][ ];
    int [ ][ ] arr={{1},{3,4},{5,6}};

3.打印一个二维数组
使用for循环来打印

int[][] arr = {{1, 2, 3, 4},{5, 6, 7, 8}, {9, 10, 11, 12}}; 
for (int row = 0; row < arr.length; row++) {
	for(int col = 0; col < arr[row].length; col++) {
		System.out.printf("%d\t", arr[row][col]);     
	}     
	System.out.println(""); } 
}
//// 执行结果 
1 2 3 4
5 6 7 8
9 10 11 12 

三丶数组中的冒泡排序,二分查找等问题

1.冒泡排序

import java.util.Arrays;

public class TestDemo1 {
    public static void main(String[] args) {
        int[] array={6,2,7,4,14,5,9,8}; //初始化一个数组
        maoPao(array);
        System.out.println(Arrays.toString(array));  //打印排序完的数组
    }
    public static void maoPao(int[] a) {
        for (int i = 0; i <a.length -1; i++) {       //外循环,确定循环的次数
            for (int j = 0; j <a.length-1-i ; j++) { //内循环,每次循环都将一个最大的数沉底
                if(a[j]>a[j+1]) {  //判断两个相邻元素的大小
                    int temp=a[j+1];
                    a[j+1]=a[j]; //大的值右移
                    a[j]=temp; //内层一轮循环之后,最大的数就沉底了
                }
            }
        }
    }
}
//执行结果为:
[2, 4, 5, 6, 7, 8, 9, 14]


2.二分查找

  • 非递归写法

public class TestDemo1 {
    public static void main(String[] args) {
        int[] array={1,2,3,4,5,6,7,8,9};
        System.out.println(binarySearch1(array,7));
    }
    public static int binarySearch1(int[] arr, int toFind) {
   	 int left=0;
   	 int right=arr.length-1;
  	 while(left<=right) {
       	 int mid=(left+right)/2;
         	if(arr[mid]>toFind) { //要查找元素在mid左边
            		right=mid-1;  
        	}else if (arr[mid]==toFind) {
           		 return mid;
       		}else {     //要查找元素在mid右边
            		left=mid+1;
        	}
    	   }
    	return  -1;
    	}
}
  • 递归写法
public class TestDemo1 {
    public static void main(String[] args) {
        int[] array={1,2,3,4,5,6,7,8,9};
        System.out.println(binarySearch(array,1,0,8));
    }
    public static int binarySearch(int[] array,int key,int left,int right) { //传入的四个参数依次是:数组名,查找元素,数组左下标,数组右下标
        if(left>right) { 
            return  -1; //没有找到,返回-1
        }
        int mid=(left+right)/2;
        if(array[mid]==key) {
            return mid; //mid==key时,mid即为要找的值
        }else if(array[mid]>key) { //mid>key,说明key在mid的左边
            return binarySearch(array,key,left,mid-1); //在mid左边继调用此方法查找key
        }else {
            return binarySearch(array,key,mid+1,right);//在mid右边继续调用此方法查找key

        }
     }
}
//执行结果 
0
发布了27 篇原创文章 · 获赞 57 · 访问量 945

猜你喜欢

转载自blog.csdn.net/A_K_L/article/details/102643132
今日推荐