u06-数组操作

150 阅读4分钟

1. 一维数组

概念: 数组就是在堆内存中开辟的一段连续的内存空间:

  • 一维数组长度不可改变,内容类型必须一致。
  • 一维数组下标从0开始,在知道位置的情况下查询快,操作费事。
  • 数组是有默认值的,如int数组中的每个值都默认为0,double数组中的每个值都默认为0.0等。

数组内存分布图

image.png

1.1 一维数组声明

概念:

  • 声明一个数组的时候,要么指定内容,要么指定长度,且不可同时指定。
  • 数组是引用数据类型,直接输出数组变量,得到的是引用数据类型的内存地址。

因为String的特权导致,char[]是可以直接打印输出的(String的底层就是char数组),所以如果非要查看char[]的内存地址,可以将其拼接一个空字符串再输出,或者对其使用 toString()

源码: /javase-start/

  • src: c.y.array.OneDimensionalArrayTest.build()
/**
 * @author yap
 */
public class OneDimensionalArrayTest {
    @Test
    public void build() {
        int[] arrA = new int[]{1, 2, 3};
        int arrB[] = {1, 2, 3};
        int[] arrC = new int[3];
        arrC[0] = 1;
        arrC[1] = 2;
        arrC[2] = 3;
        System.out.println(arrA);
        System.out.println(arrB);
        System.out.println(arrC);
    }
}    

1.2 一维数组遍历

概念: 遍历指的就是将容器(这里指数组)中的元素一个一个拿出来进行其他操作。

  • 数组一般使用 for 或者 for-each 循环来进行遍历。
  • 数组长度:使用 arr.length 来查看数组的长度。
  • Arrays.toString():快速查看一维数组内容的字符串表示形式。

源码: /javase-start/

  • src: c.y.array.OneDimensionalArrayTest.traverse()
    @Test
    public void traverse() {
        int[] nums = {1, 2, 3};
        for (int i = 0, j = nums.length; i < j; i++) {
            System.out.println(nums[i]);
        }
        for (int num : nums) {
            System.out.println(num);
        }
        System.out.println(Arrays.toString(nums));
    }

1.3 一维数组复制

概念: 数组是引用数据类型,所以复制一个数组和直接递交引用并非是同一个概念,常见的数组复制方式有如下几种:

  • 利用 for 循环复制数组。
  • 利用 System.arraycopy() 复制数组:
    • p1:原数组
    • p2:从原数组的哪个位置开始复制
    • p3:目标数组
    • p4:从目标数组的哪个位置开始粘贴
    • p5:复制多长
  • 利用 Arrays.copyOf(int[] arr, int length)
    • p1:原数组
    • p5:复制多长
    • 底层调用的 System.arraycopy()

源码: /javase-start/

  • src: c.y.array.OneDimensionalArrayTest.copy()
    @Test
    public void copy() {
        int[] arr = {1, 2, 3};

        int[] arrA = new int[arr.length];
        for (int i = 0, j = arrA.length; i < j; i++) {
            arrA[i] = arr[i];
        }
        System.out.println(Arrays.toString(arrA));

        int[] arrB = new int[arrA.length];
        System.arraycopy(arr, 0, arrB, 0, arr.length);
        System.out.println(Arrays.toString(arrB));

        int[] arrC = Arrays.copyOf(arr, arr.length);
        System.out.println(Arrays.toString(arrC));
    }

1.4 一维数组查找

概念:

  • 从一个一维数组中查找某个元素,需要遍历这个数组,用其中的每一个元素和我们要找的元素进行比较,这种方式浪费了大量的时间,很影响效率,所以我们在大量数据中查找某个元素的情况下,会使用到二分法的方式进行查找。
  • 采用二分法查找时,数据需是排好序的。

流程:

  1. 计算查找区间的中间位k:
    • (高位 + 低位) / 2
  2. arr[k] 与目标查找值进行比较:
    • 若相等,查找成功,返回k。
    • arr[k] 比目标值大,则划掉k及k后面位置上的所有元素。
    • arr[k] 比目标值小,则划掉k及k前面位置上的所有元素。
    • 重新划分查找区域(重新计算中间位),继续二分查找。

Arrays.binarySearch(int[] arr, char key):在arr数组中,用二进制搜索法搜索key。

源码: /javase-start/

  • src: c.y.array.OneDimensionalArrayTest.binarySearch()
    @Test
    public void binarySearch(){
        int target = 13;
        int result = -1;
        int[] arr = { 1, 3, 5, 7, 9, 11, 13, 15 };
        int lowIndex = 0;
        int highIndex = arr.length - 1;
        int midIndex = (lowIndex + highIndex) / 2;

        while (lowIndex <= highIndex) {

            if (arr[midIndex] == target) {
                result = midIndex;
                break;
            } else {
                if (arr[midIndex] < target) {
                    lowIndex = midIndex + 1;
                } else {
                    highIndex = midIndex - 1;
                }
            }

            midIndex = (lowIndex + highIndex) / 2;
        }
        System.out.println(result);
    }

2. 二维数组

概念: 二维数组可以看成是数组的数组,如果将二维数组看成是一个特殊的一维数组,那么这个一维数组的每一个元素都是数组。

2.1 二维数组声明

概念:

  • 声明一个二维数组的时候,要么指定内容,要么指定长度,且不可同时指定。
  • 二维数组中的每个一维数组的长度可以不同。
  • 可以利用 Arrays.deepToString(arr) 快速查看二维数组。

源码: /javase-start/

  • src: c.y.array.TwoDimensionalArrayTest.build()
/**
 * @author yap
 */
public class TwoDimensionalArrayTest {

    @Test
    public void build() {
        int[][] arrA = new int[][]{{1}, {4, 67}, {80}};
        System.out.println(Arrays.deepToString(arrA));

        int[] arrB[] = {{1}, {4, 67}, {80}};
        System.out.println(Arrays.deepToString(arrB));

        int[][] arrC = new int[2][3];
        arrC[0][0] = 1;
        arrC[0][1] = 22;
        arrC[0][2] = 313;
        arrC[1][0] = 34;
        arrC[1][1] = 311;
        arrC[1][2] = 35;
        System.out.println(Arrays.deepToString(arrC));
    }
}

2.2 二维数组遍历

概念:

  • 遍历方式:指的就是将容器(这里指数组)中的元素一个一个拿出来进行其他操作,一般使用两个 for 或者 for-each 循环来遍历二维数组。
  • 数组长度:使用 arr.length 来查看二维数组中一维数组的个数。
  • Arrays.deepToString():快速查看二维数组内容的字符串表示形式。

源码: /javase-start/

  • src: c.y.array.TwoDimensionalArrayTest.traverse()
    @Test
    public void traverse() {
        int[][] arr = {{1}, {4, 67}, {5}, {16, 17, 18, 40}};
        for (int i = 0, j = arr.length; i < j; i++) {
            for (int m = 0; m < arr[i].length; m++) {
                System.out.print(arr[i][m] + "\t");
            }
        }
        for (int[] e1 : arr) {
            for (int e2 : e1) {
                System.out.print(e2 + "\t");
            }
        }
        System.out.println(Arrays.deepToString(arr));
    }

3. 位组

概念: java.util.BitSet 的特点可以按位存储一个布尔值。

  • BitSet(int nbits):在构造位组的时候可以指定初始容量,如果不指定,默认容量64,值都是false。
  • void set(int bitIndex):将位组中bitIndex号位置上的false改为true,如果角标超出当前容量,则会触发自动扩容,每次扩容64个。
  • int size():获取位组当前的容量。
  • boolean get(int bitIndex):获取bitIndex号位置上的值,如果角标超出当前容量,不会触发自动扩容,直接返回false。

源码: /javase-start/

  • src: c.y.array.BitSetTest.api()
/**
 * @author yap
 */
public class BitSetTest {
    @Test
    public void api() {
        BitSet bitSet = new BitSet();
        bitSet.set(0);
        bitSet.set(12);
        System.out.println(bitSet.size());
        bitSet.set(64);
        System.out.println(bitSet.size());
        System.out.println(bitSet.get(0));
        System.out.println(bitSet.get(1));
        System.out.println(bitSet.get(500));
        System.out.println(bitSet.size());
    }

    @Test
    public void work01() {
        BitSet bitSet = new BitSet(365);
        int[] holidays = {1, 15, 50, 148, 185, 246, 281, 316, 326, 359};
        for (int holiday : holidays) {
            bitSet.set(holiday);
        };
        System.out.println(bitSet.get(1) ? "is holiday" : "is not holiday");
        System.out.println(bitSet.get(2) ? "is holiday" : "is not holiday");
    }
}    

4. 数据结构-栈

概念: 栈是一种后进先出(last in first out)的数据结构。

  • push():将元素推入栈顶(数组尾部),使得原栈结构的长度加1。
  • pop():将栈顶元素移除并返回,使得原栈结构的长度减1。
  • peek():将栈顶元素返回,原栈结构的长度不变。

5. 数据结构-队列

概念: 队列是一种先进先出(first in first out)的数据结构。

  • add():将元素推入队列(数组尾部),使得原队列结构的长度加1。
  • poll():队列头出队,使得原队列结构的长度减1。。
  • peek():查看队列头,原队列结构的长度不变。