数组和引用总结



文章目录

  • 数组和引用总结
  • 一、数组的基本用法
  • 1.什么是数组
  • 2.一维数组的创建
  • 3.二维数组的创建
  • 4.数组的使用
  • 4.1获取长度 & 访问元素
  • 4.2遍历数组
  • 4.3使用 for-each 遍历数组
  • 5.数组的相关练习
  • 5.1数组转字符串
  • 5.2数组拷贝
  • 5.3找数组中的最大元素
  • 5.4求数组中元素的平均值
  • 5.5查找数组中指定元素(顺序查找)
  • 5.6查找数组中指定元素(二分查找)
  • 5.7检查数组的有序性
  • 5.8数组排序(冒泡排序)
  • 5.9数组逆序
  • 5.10数组数字排列
  • 二、引用
  • 1.什么是引用
  • 2.引用的规则



一、数组的基本用法

1.什么是数组

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

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

2.一维数组的创建

基本语法:

// 动态初始化
数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 };
int[] arr = new int[]{1, 2, 3};
// 静态初始化
数据类型[] 数组名称 = { 初始化数据 };
int[] arr = {1, 2, 3};

注意: 静态初始化的时候, 数组元素个数和初始化数据的格式是一致的.

3.二维数组的创建

基本语法:

数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
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

4.数组的使用

4.1获取长度 & 访问元素

int[] arr = {1, 2, 3};
// 获取数组长度
System.out.println("length: " + arr.length); // 执行结果: 3
// 访问数组中的元素
System.out.println(arr[1]); // 执行结果: 2
System.out.println(arr[0]); // 执行结果: 1
arr[2] = 100;
System.out.println(arr[2]); // 执行结果: 100

注意事项

  1. 使用 arr.length 能够获取到数组的长度. . 这个操作为成员访问操作符. 后面在面向对象中会经常用到.
  2. 使用[ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数
  3. 使用 [ ] 操作既能读取数据, 也能修改数据.
  4. 下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常

C中数组下标越界和Java中的区别

C:未定义行为
Java:行为是确定的

4.2遍历数组

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

int[] arr = {1, 2, 3};
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}
// 执行结果
1
2
3

4.3使用 for-each 遍历数组

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

5.数组的相关练习

5.1数组转字符串

Java 中提供了 java.util.Arrays 包, 其中包含了一些操作数组的常用方法

import java.util.Arrays
int[] arr = {1,2,3,4,5,6};
String newArr = Arrays.toString(arr);
System.out.println(newArr);
// 执行结果
[1, 2, 3, 4, 5, 6]

自己实现:

import java.util.Arrays;

public class Test1 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        String result = arrToString(arr);
        System.out.println(result);
    }
    public static String arrToString(int[] arr) {
        String result = "[";
    //判定一下当前元素是否为最后一个,如果是,就不加逗号
        for (int i = 0;i <= arr.length - 1;i++) {
            result += arr[i];
            if (i != arr.length - 1) {
                result += ", ";
            } else {
                result += "";
            }
        }
        result += "]";
        return result;
    }

}

5.2数组拷贝

import java.util.Arrays;

public class Test2 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        //数组拷贝
//        int[] arr2 = copyArray(arr);
        int[] arr2 = Arrays.copyOf(arr,arr.length);
        arr[0] = 10;
        System.out.println(arr2[0]);
    }

    public static int[] copyArray(int[] arr) {
        //首要操作,创建一个新的数组;
        int[] result = new int[arr.length];
        for (int i = 0;i <= arr.length - 1;i++) {
            result[i] = arr[i];
        }
        return result;
    }
}

5.3找数组中的最大元素

public class Test3 {
    public static void main(String[] args) {
        //寻找数组中的最大元素
        int[] arr = {5, 7, 3, 8, 9, 1, 10};
        int result = max(arr);
        System.out.println(result);
    }

    //打擂台的方法,谁大谁留在台上,否则就下去
    public static int max(int[] arr) {
        int result = arr[0];
        for (int i = 0;i <= arr.length-1;i++) {
            if (arr[i] > result) {
                result = arr[i];
            }
        }
        return result;
    }
}

5.4求数组中元素的平均值

public class Test4 {
    public static void main(String[] args) {
        //求数组平均值
        int[] arr = {9,3,4,5,1,8,6,10};
        double result = avg(arr);
        System.out.println(result);
    }

    public static double avg(int[] arr) {
        int sum = 0;
        for (int x : arr) {
            sum += x;
        }
        return (double)sum / arr.length;
    }
}

5.5查找数组中指定元素(顺序查找)

代码在5.6二分查找中,未拆开

5.6查找数组中指定元素(二分查找)

public class Test5 {
    public static void main(String[] args) {
        //“查找”有两种风格
        //1.给定位置,查找值
        //2.给定值,查找位置(数组下标)
        //查找数组元素的位置
        //int[] arr = {8,5,6,9,3,7,1};
        //int pos = search(arr,3);
        //System.out.println(pos);

        //二分查找
        //二分查找必须应用于有序数组
        int[] arr = {2,3,4,5,7,13};
        int pos = binarySearch(arr,5);
        System.out.println(pos);
    }

    //直接去整个数组的中间元素,用中间元素和待查找元素进行对比
    public static int binarySearch(int[] arr, int toSearch) {
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (toSearch < arr[mid]) {
                //左侧区间查找,淘汰掉右侧区间
                right = mid - 1;
            } else if (toSearch > arr[mid]) {
                //右侧区间查找,淘汰掉左侧区间
                left = mid + 1;
            } else {
                //相等
                return mid;
            }
        }
        return -1;
    }

    public static int search(int[] arr, int toSearch) {
        for (int i = 0;i <= arr.length - 1;i++) {
            if (arr[i] == toSearch) {
                return i;
            }
        }
        //返回-1表示没找到
        return -1;
    }
}

5.7检查数组的有序性

public class Test6 {
    public static void main(String[] args) {
        //验证数组的有序性
        int[] arr = {2,3,4,5,6,7};
        System.out.println(isSorted(arr));
    }

    //按照升序来比较
    //依次比较数组中的两个相邻元素,如果所有的相邻元素之间都是有序的话,
    //就认为整个数组是有序的
    //只要找到一个反例,就是无序的
    public static boolean isSorted(int[] arr) {
        for (int i = 0; i < arr.length - 1;i++) {
            if (arr[i] > arr[i+1]) {
                return false;
            }
        }
        return true;
    }
}

5.8数组排序(冒泡排序)

import java.util.Arrays;

public class Test7 {
    public static void main(String[] args) {
        //冒泡排序(升序来算)
        //一趟比较下来,就可以将最大的元素放到最后,或将最小的元素放到最前
        int[] arr = {9,5,2,7,3,6};
        bubbleSort(arr);
        //Java标准库中提供了一个现成的排序算法Array.sort()
        //Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }

    //这个代码,可以直接在方法内部修改数组的内容
    //也可以创建新数组,以返回值的方式返回新数组
    //数组这样的类型,在方法内部做出修改,也能影响到实参的内容
    public static void bubbleSort(int[] arr) {
        //如果从前往后遍历进行比较交换,就把最大元素放到最后
        //如果从后往前遍历进行比较交换,就把最小元素放到最前
        //[0,bound)已排序区间
        //[bound,length)待排序区间
        for (int bound = 0;bound < arr.length;bound++) {
            for (int cur = 0;cur < arr.length - bound - 1;cur++) {
                if (arr[cur] > arr[cur + 1]) {
                    int tmp = arr[cur];
                    arr[cur] = arr[cur + 1];
                    arr[cur + 1] = tmp;
                }
            }
        }
    }
}

5.9数组逆序

import java.util.Arrays;

public class Test8 {
    public static void main(String[] args) {
        int[] arr = {9,5,2,7,3,6,10};
        //数组逆序
        reverse(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void reverse(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            int tmp = arr[right];
            arr[right] = arr[left];
            arr[left] = tmp;
            left++;
            right--;
        }
    }
}

5.10数组数字排列

import java.util.Arrays;

public class Test9 {
    public static void main(String[] args) {
        int[] arr = {9,4,2,7,3,6,10};
        //对数组进行重新排列
        //排列之后偶数在前,奇数在后
        //从前往后排列,找到一个奇数
        //再从后往前,找到一个偶数
        //交换这两元素,直到两个下标重合
        transform(arr);
        System.out.println(Arrays.toString(arr));
    }

    public static void transform(int[] arr) {
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            while (left < right && arr[left] % 2 == 0) {
                left++;
            }
            while (left < right && arr[right] % 2 != 0) {
                right--;
            }
            if (left < right) {
                int tmp = arr[right];
                arr[right] = arr[left];
                arr[left] = tmp;
            }
        }
    }
}

二、引用

1.什么是引用

String s = "Hello World"; // 这里的 s 的类型是 String 类型的引用;该引用指向了一个String 类型的对象。
int[] a = { 1, 2, 3, 4, 5 }; // 这里的 a 的类型是 int[] 类型的引用;该引用指向了一个元素类型是 int 的数组类型对象。

引用其实通俗的讲也就是别名。

注意:
1.一个对象可以拥有多个别名;
2.一个引用只能对应到一个对象

2.引用的规则

注1:
(1)只有引用指向对象;没有对象指向引用;也没有引用指向引用;更没有对象指向对象;
(2)对象可以被多个引用指向;
(3)操作引用,其实操作的是引用指向的对象;
(4)一个对象至少得有一个引用指向,如果一个引用都没有了,说明这个对象无法在代码中被使用了,此时这个对象就会被垃圾回收器当成垃圾从而回收并释放内存空间;

注2:
“=”赋值操作的是引用的指向,对对象本身并无影响;

注3:
(1)引用是一种数据类型,用来指向对象;
(2)对引用进行大部分操作实际上都是操作的该引用指向的对象;
(3)当多个引用指向同一个对象时,通过哪个引用修改了对象,其他引用都可以看到对象;
(4)当一个引用不指向对象时,要求访问其指向的对象,就会遇到NullPointerException;

注3:
(1)引用和对象都是一种数据组织形式,所以都是存放在内存中的;
(2)对象一定保存在堆上,但引用则不一定;
(3)引用是一类只能用来指向对象的数据类型;
(4)引用可以指向对象,也可以不指向对象;
(5)解引用操作就是通过引用找到对象;
(6)Java中无法直接接触到对象,都是通过引用接触到对象;
(7)对一个空的引用做到解引用操作,会出现NullPointerException;
(8)JVM为了便于管理,将其管理的内存人为划分为6个区域:
①PC区;②虚拟机栈;③本地方法栈;④堆;⑤方法区;⑥运行时常量池;

注4:
(1)空指针表示指针中存的地址对应的内存是一个非法内存;
(2)空引用表示该引用里面的所持有的地址对应的对象,是一个非法的对象;

注5:
(1)null和0号地址,不一定直接相关;
(2)null存的地址,不一定是0;
(3)不能针对null这样的引用进行“解引用”,指的就是不能够访问这个对象的成员;

注6:
(1)Build:编译错误; 编译一次
(2)Exception:运行错误; 运行可能是N次

注7:
(1)使用null可以表示一个非法值;
(2)null不能赋值给内置类型,只能赋值给引用类型
eg:不能赋值为int,可以赋值给Integer。