【Java SE】数组的定义与使用;数组的使用;如何理解引用,形参,实参;二分查找;冒泡排序;数组逆置;数组的拷贝

数组的定义与使用

1. 数组基本用法

1.1 什么是数组

数组的本质就是让我们能“批量”创建相同类型的变量

例如:

如果要创建两个变量: int a; int b;

如果要创建多个变量,就需要使用数组

注意事项:在Java中,数组中包含的变量必须的相同类型

1.2 创建数组

基本语法

数据类型[ ] 数组名称 = {初始化数据}

数据类型[ ] 数组名称 = new 数据类型 [ 数组大小 ]

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

public static void main(String[] args) {
    int[] array = {1, 2, 3,};
    int[] array1 = new int[3];
    int[] array2 = new int[]{1, 2, 3};

1.3 数组的使用

1.获取长度
int[] array = {1,2,3};
System.out.println("length: " + array.length);
//执行结果:
3
2.访问元素
int[] array = {1,2,3};
System.out.println(array[0]);
System.out.println(array[1]);
//执行结果:
1
2
3.修改元素
int[] array = {1,2,3};
array[1] = 20;
System.out.println(array[1]);
//执行结果:
20
4.输出数组
int[] array = {1, 2, 3, 4, 5, 6};
//array是一个引用变量,引用指向一个对象,引用存储的是变量的地址
for (int i = 0; i < array.length; i++) {
    System.out.print(array[i] + " ");
}
//执行结果:
1 2 3 4 5 6
int[] array = {1,2,3,4,5,6};
for(int x : array){
    System.out.print(x + " ");
}
//执行结果:
1 2 3 4 5 6
int[] array = {1,2,3,4,5,6};
//Arrays.toString(数组名) 将参数中的数组以字符串的形式输出
String ret = Arrays.toString(array);
System.out.println(ret);
System.out.println(Arrays.toString(array));
//执行结果:
[1,2,3,4,5,6]
[1,2,3,4,5,6]
  • 数组的使用注意事项
    使用 arr.length 能够获取到数组的长度, . 这个操作为成员访问操作符,后面在面向对象中会经常到
  • 使用 [ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数
  • 使用 [ ] 操作既能读取数据, 也能修改数据.
  • 下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常

2. 数组作为方法的参数

2.1 基本用法

代码示例:打印数组内容

public static void main(String[] args) {
    int[] array = {1, 2, 3, 4, 5, 6};
    print(array);
}
public static void print(int[] array) {
    for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + " ");
    }
}
//执行结果
1 2 3 4 5 6

注意事项:print方法中的array是形参,main函数中array是实参

2.2 如何理解引用,形参,实参(重点)

public static void func1(int[] array) {
    array = new int[]{7, 8, 9, 4, 5, 6};//假设形参array引用 指向的地址是0x45
}
public static void func2(int[] array) {
    array[0] = 99;
}
public static void main(String[] args) {
    int[] array = {1, 2, 3, 4, 5, 6}; //假设实参array引用 指向的地址是0x12
    System.out.println(Arrays.toString(array));
    func1(array);//调用func1 将实参array指向的地址 传给fun1的形参array  形参array也指向0x12
    //在fun1内 只是将形参array指向的地址变为了0x56 实参array指向的地址仍是0x12
    System.out.println(Arrays.toString(array));//打印的是实参array 指向0x12  所以结果是[1,2,3,4,5,6]
    func2(array);//调用func2 将实参array指向的地址 传给func2的形参array  形参array也指向0x12
    //在func2内,将形参array指向的地址0x12 的0下标的值改成了99 
    System.out.println(Arrays.toString(array));
    // 因为实参指向的地址是0x12 而0x12中 0 下标的值被改成了99
    // 所以结果是[99,1,2,3,4,5,6]
}

在函数内部修改数组内容,函数外部也发生改变。此时数组名array是一个“引用”,当传参的时候,是按照引用传参,引用可以理解为指针,一个引用只能保存一个对象的地址,Java将数组设定成引用类型,进行数组传参时,只是将数组的地址传入到方法形参中.

2.3 认识null

null在Java中表示"空引用",也就是一个无效的引用

int [] array = null;
System.out.println(arr[0]);
//执行结果 :空指针异常
Exception in thread "main" java.lang.NullPointerException 

null 的作用类似于 C 语言中的 NULL (空指针), 都是表示一个无效的内存位置. 因此不能对这个内存进行任何读写操作. 一旦尝试读写, 就会抛出 NullPointerException

2.4 初识JVM内存区域划分

JVM 的内存被划分成了几个区域

程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址.
虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int[] array 这样的存储地址的引用就是在这里保存.引用不一定在栈上,如果变量的性质是局部变量,它一定在栈上,实例成员变量不一定在栈上
本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int[{1, 2,3} ]
方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后代码等数
据. 方法编译出的的字节码就是保存在这个区域.
运行时常量池(Runtime Constant Pool): 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从 JDK1.7 开始, 运行时常量池在堆上).
局部变量和引用保存在栈上, new 出的对象保存在堆上.
堆的空间非常大, 栈的空间比较小.
堆是整个 JVM 共享一个, 而栈每个线程具有一份(一个 Java 程序中可能存在多个栈).

3. 数组作为方法的返回值

代码示例:将数组扩大二倍 (无返回值)

public static void main(String[] args){
    int[] array = {1,2,3,4,5,};
    transform(array);
    System.out.println(Arrays.toString(array));
}
public static void transform(int [] array){
    for(int i =0; i < array.length; i++){
        array[i] = 2 * array[i];  
    }
}
//执行结果:
[2,4,6,8,10]

注意事项:这种方法,改变了原数组的值,如果我们不希望破坏原数组,就需要在方法中创建一个新数组,并由方法返回出来

代码示例:将数组扩大二倍(有返回值)

public static void main(String[] args){
    int[] array = {1,2,3,4,5,};
    int[] ret1 = transform1(array);//定义一个数组ret1 用来接收transform1的返回值
    System.out.println(Arrays.toString(ret1));// 打印ret1
    System.out.println(Arrays.toString(array));//打印原数组array
}
public static int[] transform1(int [] array){
    for(int i = 0; i < array.length; i++){
        ret[i] = 2 * array[i]
    }
    return ret;
}
//执行结果:
[2,4,6,8,10]
[1,2,3,4,5]

这样的话就不会破坏原有数组了.另外由于数组是引用类型, 返回的时候只是将这个数组的首地址返回给函数调用者, 没有拷贝数组内容, 从而比高效

4. 数组练习

4.1 实现一个自己版本的数组转字符串

代码示例

public static String myToString(int [] array){
    if(array == null){
        return null;
    }
    String str = "[";
    for(int i = 0; i <array.length; i++){
        str = str + array[i];
        if(i < array.length - 1 ){
            str = str + ",";
        }
    }
    str = str + "]";
    return str;
}
public static void main(String[] args){
    int [] array = {1,2,3,4,5};
    System.out.println(myToString(array));
}
//执行结果
[1,2,3,4,5]

4.2 输出一个数组中的最大值

代码示例

public static void main(String[] args) {
    int [] array = {5,12,6,8,9};
    System.out.println(maxNum(array));
}
public static int maxNum(int [] array){
    if( array.length == 0 || array == null){
        return -1;
    }
    int max = array[0];
    for (int i = 1; i < array.length;i++){
        if (max < array[i]){
            max = array[i];
        }
    }
    return max;
}

先将max设置为数组中的第一个元素,遍历数组,如果某个元素大于max,那么就将它的值赋给max

4.3 给定一个整型数组,求出数组中元素的平均值

代码示例

public static void main(String[] args) {
    int [] array = {1,2,3,4,5};
    System.out.println(avg(array));
}
public static double avg(int[]array){
    int sum = 0;
    for (int i = 0; i < array.length; i++){
        sum += array[i] ;
    }
    return (double) sum / (double) array.length;
}
//执行结果:
3.0

注意事项:平均值有可能是小数,所以要用返回值类型是double

4.4 无序数组找某个元素的下标

代码示例

public static void main(String[] args){
    int [] array = {8,7,4,5,2,1,3,6,9};
    System.out.println(findNum(array,5));
}
public static int findNum(int[]array,int key){
    for(int i = 0;i < array.length; i++){
        if(array[i] == key){
            return i;
        }
    }
    return -1; //表示没找到
}
//执行结果:
3

遍历数组,当某个下标的值和要找的值相等时,返回这个下标,如果没有,则返回-1

4.5 有序数组找某个元素的下标(二分查找)

以升序数组为例, 二分查找的思路是先取中间位置的元素, 看要找的值比中间元素大还是小. 如果小, 就去左边找;否则就去右边找

代码示例

public static void main(String[] args){
    int [] array = {1,2,3,4,5,6,7,8,9};	
    System.out.println(binarySearch(array,6));
}
public static int binarySearch(int [] array,int key){
    int left = 0;
    int right = array.length - 1;
    while(left <= right){
        int mid = (left + right) / 2;
        if(array[mid] < key){ //在右区间找
            left = mid + 1; 
        }else if(array[mid > key]){//在左区间找
            right = mid -1;
        }else{ 	//找到了
            return mid;
        }
    }
    return -1;  //表示没有找到
}
//执行结果
5

4.6 判断一个整型数组是否是升序的

代码示例

public static void main(String[] args){
    int [] array = {1,2,3,8,5,6};
    System.out.println(ifup(array));
}
public static boolean ifUP(int [] array){
    for(int i = 0; i < array.length - 1; i++){
        if( array[i] > array[i+1]){
            return false;
        }
        return true;
    }
}
//执行结果
false

注意事项:for循环的边界要小于数组长度减1,否则会下标溢出

4.7 数组排序(冒泡排序)

代码示例

public static void main(String [] args){
    int [] array = {3,5,9,4,8,7,1,6,2}
    bubbleSort(array);//调用bubbleSort方法
    System.out.println(Assary.toString(array));//输出数组array中的元素
}
public static void bubbleSort(int [] array){
    for(int i = 0; i < array.length -1; i++){ //排序的次数
        boolean flg = false; 
        //定义flg 用来记录是否交换,交换为true,没交换为false, 每次排序前flg初始值为false
        for(int j = 0; j <array.length -1 -i; j++){ //交换2个数
            if(array[j] > array[j+1]){
                int tmp = array[j];
                array[j] = array[j+1];
                array[j+1] = tmp;
                flg = true;  //说明交换了
            }
        }
        if(flg == false){
            break; //没交换, 说明排序已经完成,不再需要继续进行后续的循环
        }
    }
}
//执行结果
[1,2,3,4,5,6,7,8,9]

4.8 数组排序 用Arrays.sort排序

代码示例

public static void main(String[] args) {
    int [] array = {3,2,1,6,5,4,7,8,9};
    Arrays.sort(array);
    System.out.println(Arrays.toString(array));
}
//执行结果
[1,2,3,4,5,6,7,8,9]

4.9 用Arrays.fill 填充数组

代码示例

public static void main15(String[] args) {
    int [] array = new int [10];
    Arrays.fill(array,2,4,55);//在[2,4)下标中放入55 
    System.out.println(Arrays.toString(array));
}
//执行结果
[0,0,55,55,0,0,0,0,0,0]

4.10 数组逆置

代码示例

public static void main16(String[] args) {
    int [] array = {1,2,3,4,5,6,7,8,9};
    reverse(array);
    System.out.println(Arrays.toString(array));
}
public static void reverse(int[]array){
    int i = 0;
    int j = array.length-1;
    while (i < j){
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
        i++;
        j--;
    }
}
//执行结果
[9,8,7,6,5,4,3,2,1]

4.11 整型数组数字排列,偶数在前,奇数在后

代码示例

public static void main(String[] args) {
    int [] array = {1,2,3,4,5,6};
    transForm(array);
    System.out.println(Arrays.toString(array));
}
public static void transForm(int [] array){
    int i = 0;
    int j = array.length-1;
    while (i < j){
        while (array[i] % 2 == 0 && i < j){
            i++;
        }// 循环结束后i下标的元素一定是奇数
        while (array[j] % 2 != 0 && i < j){
            j--;
        }// 循环结束后j下标的元素一定是偶数
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp; //交换两个位置的元素
    }
}
//执行结果
[6,2,4,3.5.1]

4.12 数组的拷贝

for循环的拷贝

public static void main(String[] args) {
    int [] array = {1,2,3,4,5,6};
    System.out.println(Arrays.toString(copy(array)));
}
public static int[] copy(int [] array){
    int [] copy = new int[array.length];
    for (int i = 0 ; i < array.length; i++){
        copy[i] = array[i];
    }
    return copy;
}
//执行结果
[1,2,3,4,5,6]

Arrays.copyOf 拷贝

public static void main(String[] args) {
    int [] array = {1,2,3,4,5,6};
    int [] ret = Arrays.copyOf(array,array.length);//Arrays.copyOf(拷贝的数组名,拷贝的长度)
    System.out.println(Arrays.toString(ret));
    //执行结果
    [1,2,3,4,5,6]

Arrays.copyOfRange 拷贝

public static void main(String[] args){
    int [] array = {1,2,3,4,5,6};
    int[] arr = Arrays.copyOfRange(array,1,3);
//拷贝一部分数据,Arrays.copyOfRange(数组名,拷贝范围[1,3) )
System.out.println(Arrays.toString(arr));
}
//执行结果
[2,3]

System.arraycopy 拷贝

public static void main(String[] args){
    int [] array = {1,2,3,4,5,6};
    int [] copy = new int[array.length];
System.arraycopy(array,0,copy,0,array.length);
//System.arraycopy(源数组,从源数组的0开始拷贝,拷贝到copy数组,从copy的0下标开始,拷贝的长度)
System.out.println(Arrays.toString(copy));
}
//执行结果
[1,2,3,4,5,6]

array.clone 拷贝

public static void main(String[] args){
    int [] array = {1,2,3,4,5,6};
    int [] array1 = array.clone();//array.clone  克隆一个副本 copy引用指向副本的地址,
System.out.println(Arrays.toString(array1));
}
//执行结果
[1,2,3,4,5,6]

5. 二维数组

二维数组本质上也就是一维数组,只不过每个元素又是一个一维数组

基本语法

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

代码示例

public static void main(String[] args) {
    int [][]array = {{1,2,3},{4,5,6}};
    int [][]array2 = new int[][]{{1,2,3},{4,5,6}};
    int [][]array3 = new int [2][3];
}

打印二维数组

代码示例1

public static void main(String[] args) {
    int [][]array = {{1,2,3},{4,5,6}};
    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();
    }
}
//执行结果
1 2 3
4 5 6

代码示例2

public static void main(String[] args) {
    int [][]array = {{1,2,3},{4,5,6}};    
    for (int[] ret: array) {
        for (int x: ret) {
            System.out.print(x + " ");
        }
        System.out.println();
    }
}
//执行结果
1 2 3
4 5 6

代码示例3

public static void main(String[] args) {
    int [][]array = {{1,2,3},{4,5,6}};
System.out.println(Arrays.deepToString(array));
}
//执行结果
[[1,2,3],[4,5,6]]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值