冯宝宝说java:数组

第四章:数组............................................................................................................................... 2

1.数组概述和特点......................................................................................................................... 2

1.1数组的概念....................................................................................................................... 2

1.2数组的创建....................................................................................................................... 2

1.2.1动态创建数组......................................................................................................... 2

1.2.2静态创建数组......................................................................................................... 2

1.3数组的基本操作................................................................................................................ 3

1.4数组的默认初始化............................................................................................................ 5

1.5 JVM中的堆和栈(重点)..................................................................................................... 5

2.数组常见操作............................................................................................................................. 6

2.1获取数组的最值................................................................................................................ 6

2.2通过值获取索引................................................................................................................ 6

2.3数组反序输出................................................................................................................... 7

2.4数组元素删除................................................................................................................... 8

2.5数组冒泡排序................................................................................................................... 8

2.6二分法查找....................................................................................................................... 9

3.Arrays工具类........................................................................................................................... 10

3.1 toString方法................................................................................................................... 10

3.2 equals判断...................................................................................................................... 11

3.3 sort排序......................................................................................................................... 11

3.4 二分法查找.................................................................................................................... 11

3.5 fill填充数组.................................................................................................................... 11

3.6 数组拷贝....................................................................................................................... 12

4.数组知识点补充....................................................................................................................... 12

4.1 for-each循环遍历............................................................................................................ 12

4.2 main方法的形参............................................................................................................. 13

4.3方法的可变参数.............................................................................................................. 14

5.二维数组.................................................................................................................................. 14

5.1二维数组的定义.............................................................................................................. 14

5.2二维数组的创建.............................................................................................................. 14

1.数组概述和特点

1.1数组的概念

数组概念:数组就是一种能够存放相同数据类型有序集合。(通俗来讲数组其实就是一个容器)。

1.2数组的创建

1.2.1动态创建数组

语法格式:元素类型[]  数组名 = new 元素类型[数组长度];

          元素类型  数组名[] = new 元素类型[数组长度];

注意:数组的声明建议大家使用第一种方式,避免数组名混淆。

【示例】

public static void main(String[] args) {

    // 创建3个空间的int类型数组

    int[] arr1 = new int[3];

    // 创建5个空间的String类型数组

    String[] arr2 = new String[5];

}

1.2.2静态创建数组

语法格式:元素类型[]  数组名 = new 元素类型[]{元素1, 元素2, 元素3,…};

注意:使用静态的方式来创建数组,数组的长度由元素个数来确定。

【示例】

public static void main(String[] args) {

    // 创建指定内容的int类型数组

    int[] arr1 = new int[]{1, 2, 3, 4, 5};

    // 创建指定内容的String类型数组

    String[] arr2 = new String[]{"11", "22", "33", "44"};

}

除了用new关键字来产生数组以外,还可以直接在定义数组的同时就为数组元素分配空间并赋值。

语法格式:元素类型[]  数组名 = {元素1, 元素2, 元素3,…};

【示例】

public static void main(String[] args) {

    // 创建指定内容的int类型数组

    int[] arr1 = {1, 2, 3, 4, 5};

    // 创建指定内容的String类型数组

    String[] arr2 = {"11", "22", "33", "44"};

}

注意事项:

  1. 数组类型可以是任何数据类型,包括基本类型和引用类型,例如String[]和float[]。
  2. 数组中存放元素的类型,必须是创建数组时指定的类型,不允许出现混合类型。
  3. 创建一个数组时,必须指定数组长度,创建成功数组的大小就不可以改变了。

1.3数组的基本操作

数组中的元素,我们可以通过下标(索引)来访问,索引从0开始。

数组索引的取值范围为:[0,数组长度-1],如果超出索引范围来操作数组元素,会抛出ArrayIndexOutOfBoundsException异常。

  • 数组的赋值操作

【示例】

public static void main(String[] args) {

// 初始化5个空间的int类型数组

    int[] arr = new int[5];

    // 添加元素

    arr[0] = 11; // 给第一个元素赋值

    arr[1] = 22; // 给第二个元素赋值

    arr[2] = 22; // 给第三个元素赋值

    // 修改第二个元素的值

    arr[1] = 222;

}
  • 数组的取值操作

【示例】

public static void main(String[] args) {

    // 创建指定内容的int类型数组

    int[] arr = {1, 2, 3, 4, 5};

    // 获取元素

    int num1 = arr[0]; // 获取第一个元素

    int num2 = arr[1]; // 获取第二个元素

    int num3 = arr[2]; // 获取第三个元素

}
  • 获取数组的长度

【示例】

public static void main(String[] args) {

    // 创建指定内容的int类型数组

    int[] arr = {1, 2, 3, 4, 5};

    // 通过length属性,来获取数组的长度

    System.out.println(arr.length); // 输出:5

}

注意事项:

  1. 通过length属性获取到的数组长度和开辟的内存空间的长度一致。
  2. 某些情况下,实际添加元素的个数(不算默认值元素),可能会小于了数组的长度。
  • 通过for循环遍历数组

【示例】

public static void main(String[] args) {

    // 创建指定内容的int类型数组

    int[] arr = {1, 2, 3, 4, 5};

    // 通过length属性,获取数组元素的个数

    int length = arr.length;

    // 通过for循环,遍历数组所有元素

    for(int i = 0; i < length; i++) {

       // 通过下标获取数组中的元素

       System.out.println("第"+(i+1)+"个元素值:" + arr[i]);

    }

}

因为数组的内存空间是连续的,我们通过数组的首地址+索引就能快速的找到数组对应的元素值,从而得出数组的优点:查找快。

 

索引操作数组原理:数组首地址 + 存放数据的字节数*索引。

【随堂练习】

1、 获取10个学生的成绩,然后保存在数组中,最后计算学生的总分和平均分。

1.4数组的默认初始化

数组是引用类型,只要数组一经分配空间,那么数组中的每个元素都会被隐式的设置一个默认值。

以下是针对不同数据类型的默认值:

1、整数类型(byte、short、int、long)的基本类型变量的默认值为0。

2、浮点型(float、double)的基本类型变量的默认值为0.0。

3、字符型(char)的基本类型变量的默认为 “/u0000”。

4、布尔性的基本类型变量的默认值为 false。

5、引用类型的变量是默认值为 null(null就是空对象)。

1.5 JVM中的堆和栈(重点)

JVM是基于堆栈的虚拟机,堆栈是一种数据结构,是用来存储数据的。对于一个Java程序来说,它的运行就是通过对堆栈的操作来完成的。

【栈内存stack

栈内存:用来存放局部变量。

当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。 

栈内存特点:

  1. 栈内存存储特性为:“先进后出,后进先出”。
  2. 栈是一个连续的内存空间,由系统自动分配,速度快!
  3. 虚拟机会为每个线程创建一个栈,用于存放该线程执行方法的信息。

【堆内存heap

堆内存:用来存储创建好的对象和数组(数组也是对象)

在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。 
引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。 

数组和对象在没有引用变量指向它的时候,数组或对象本身占用的堆内存就变成垃圾,不能再被使用,然后由Java虚拟机的自动垃圾回收器来管理释放该内存。 

堆内存特点:

  1. 虚拟机中只有一个堆,被所有的线程共享。
  2. 堆是一个不连续的内存空间,分配灵活,但速度慢!

【思考一】

public static void main(String[] args) {

    int[] arr1 = {1, 2, 3, 4, 5};

    int[] arr2 = arr1;

    arr2[2] = 33;

    System.out.println(arr1[2]); // 输出结果为???

}

【思考二】

public static void main(String[] args) {

    int[] arr1 = {1, 2, 3};

    int[] arr2 = arr1;

    arr1 = null;

    System.out.println(arr1[2]); // 输出结果为???

    System.out.println(arr2[2]); // 输出结果为???

}

2.数组常见

操作

2.1获取数组的最值

需求:获取数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}的最大值,也就是该数组的元素90。

实现:先假设第一个元素就是最大值,并赋值给maxValue变量保存,然后依次取出数组中的元素和maxValue作比较,如果取出元素大于maxValue,那么把该元素设置为最大值。

【示例】

思考

/**

* 获取数组的最大值

* @param arr 需要查询的数组

* @return 返回查询到的最大值

*/

public static int maxElement(int[] arr) {

    // 假设第一个元素的值就是最大值

    int max = arr[0];

    // 遍历数组元素,依次和假设的最大值作比较

    for(int i = 1; i < arr.length; i++) {

       // 取出每个元素的值和value作比较

       if(arr[i] > max) {

           // 推翻假设,更新最大值

           max = arr[i];

       }

    }

    return max;

}

:获取数组中最大值的索引,我们该怎么去做呢?

2.2通过值获取索引

需求:获取元素59在数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}中的索引。

实现:通过for循环来遍历数组,把需要查询的值和数组中的元素一一做比较,如果需要查询的值和某个元素相等,则返回索引值并结束方法。如果循环完毕都没查找到,则返回-1。

【示例】

/**

* 根据value值,获取它在数组中的索引位置

* @param arr 需要查询的数组

* @param value 需要判断的值

* @return 找到,则返回对应的索引;未找到,则返回-1

*/

public static int search(int[] arr, int value) {

    // 遍历数组,把数组中的元素依次和value作比较

    for(int i = 0; i < arr.length; i++) {

       // 取出元素值和value作比较

       if(arr[i] == value) {

           return i; // 找到相同的元素,返回索引位置

       }

    }

    // 未找到,则返回-1

    return -1;

}

2.3数组反序输出

需求:将数组反序输出,原数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72},反序输出后{72,59,28,45,76,77,18, 90,12,5}。

实现(一):引入一个外部数组变量,用于保存反序后的数组,然后把原数组中的元素倒序保存于新创建的数组中。

【示例一】

/**

* 将数组反序输出

* @param arr 需要反序的数组

* @return 返回反序后的数组

*/

public static int[] reverseOrderArray(int[] arr) {

    // 定义一个反序后的数组

    int[] desArr = new int[arr.length];

    // 把原数组元素倒序遍历

    for(int i = 0; i < arr.length; i++) {

       // 把arr的第i个元素赋值给desArr的最后第i个元素中

       desArr[arr.length - 1 - i] = arr[i];

    }

    // 返回倒序后的数组

    return desArr;

}

实现(二):直接对数组中的元素进行收尾交换。

【示例二】

/**

* 将数组反序输出

* @param arr 需要反序的数组

*/

public static void reverseOrderArray(int[] arr) {

    // 把原数组元素倒序遍历

    for(int i = 0; i < arr.length/2; i++) {

       // 把数组中的元素收尾交换

       int temp = arr[i];

       arr[i] = arr[arr.length - i - 1];

       arr[arr.length - i - 1] = temp;

    }

}

2.4数组元素删除

需求:删除数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}索引为2的元素,删除后:{5, 12, 18, 77, 76, 45, 28, 59, 72,0}。

实现:把数组索引2以后的元素向前移动一位,最后把数组的最后一个元素的值设置为默认值(整数类型的默认值为0)。

【示例】

/**

* 根据索引删除数组中的元素

* @param arr 需要删除元素的数组

* @param index 需要删除数组元素的索引

*/

public static void deleteElement(int[] arr, int index) {

    // 第一步:判断索引是否合法

    if(index < 0 || index >= arr.length) {

       System.out.println("索引越界");

       return; // 索引不合法,直接结束方法

    }

    // 第二步:从index个元素开始,将后一个元素向前移动一位

    for(int i = index; i < arr.length - 1; i++) {

// 将后一个元素向前移动一位

       arr[i] = arr[i + 1];

    }

    // 第三步:将最后一个元素设置为默认值

    arr[arr.length - 1] = 0;

}

数组的缺点:因为数组是连续的内存空间,当数组进行删除和插入操作的时候,效率相对低下!

2.5数组元素插入

需求:在数组{5, 12, 90, 18, 77, 76, 45, 28, 59, 72}索引为2的位置插入元素222,插入后:{5, 12, 222, 90, 18, 77, 76, 45, 28, 59, 72}。

实现:首先准备给数组扩容,然后把插入索引位置之后的元素往后移动一位,最后在插入索引的位置插入元素。

【示例】

/**

* 在数组指定位置插入元素

* @param arr 需要插入元素的数组

* @param index 插入元素的位置

* @param value 需要插入的元素值

* @return 返回插入元素成功的数组

*/

public static int[] insertElement(int[] arr, int index, int value) {

    // 第一步:判断索引是否合法

    if(index < 0 || index >= arr.length) {

       System.out.println("索引越界");

       // 抛出一个索引越界异常(异常第六章学习)。

       throw new ArrayIndexOutOfBoundsException("索引越界:"+index);

    }

    // 第二步:给数组扩容

    // 创建一个更大的数组

    int[] newArr = new int[arr.length + 1];

    // 把原数组中的数据,复制给新创建的数组

    for (int i = 0; i < arr.length; i++) {

       newArr[i] = arr[i];// 拷贝操作

    }

    // 让arr指向堆里面的newArr数组

    arr = newArr;

    // 第三步:插入索引位置之后的元素往后移动一位

    for (int i = arr.length - 2; i >= 2; i--) {

       arr[i + 1] = arr[i];

    }

    // 第四步:给index索引位置赋值

    arr[index] = value;

    // 返回插入元素成功的数组

    return arr;

}

2.6数组冒泡排序

工作原理:重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名。

升序示例】


/**

* 对数组进行升序排列(冒泡排序)

* @param arr 需要排序的数组

*/

public static void sort(int[] arr) {

    // 外侧循环控制趟数,一共要执行arr.length-1趟

    for (int i = 0; i < arr.length - 1; i++) {

       // 假设本次循环就已经排序成功

       boolean flag = true;

       // 内侧循环控制每趟比较的次数

       for (int j = 0; j < arr.length - i - 1; j++) {

           // 如果上一个大于下一个,则交换

           if (arr[j] > arr[j + 1]) {

              int temp = arr[j];

              arr[j] = arr[j + 1];

              arr[j + 1] = temp;

              // 如果发生交换,则证明没有排序成功

              flag = false; // 推翻假设

           }

       }

       // 根据flag值,判断是否需要继续排序

       if (flag) break;

}

2.7二分法查找

二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

示例

public static void main(String[] args) {

    // 使用二分法查找的数组,必须是有序数组

    int[] arr = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20};

    // 调用二分法查找,找到查找元素的索引

    int index = binarySearch(arr, 18);

    System.out.println(index); // 输出:9

}

/**

* 使用二分法查找元素的索引

* @param arr 需要查找的数组

* @param value 需要查找的元素值

* @return 如果返回值为正数,则证明找到;如果返回-1,则证明没找到。

*/

public static int y(int[] arr, int value) {

    // 最小索引

    int min = 0;

    // 最大索引

    int max = arr.length - 1;

    // 开始循环查找

    while(true) {

       // 获取中间索引

       int mid = (min + max)/2;

       // 如果arr[mid]>value,则证明在上半区

       if(arr[mid] > value) {

           // 更新max的值

           max = mid - 1;

       }

       // 如果arr[mid]<value,则证明在下半区

       else if(arr[mid] < value) {

           // 更新min的值

           min = mid + 1;

       }

       // 如果arr[mid]==value,则证明找到

       else {

           return mid;

       }

       // 如果min>max,则证明没找到该值

       if(min > max) {

           return -1;

       }

    }

}

3.Arrays工具类 

Arrays用于操作数组工具类,里面定义了常见操作数组的静态方法。

注意:要使用Arrays工具类,必须导入Arrays工具类。

import java.util.Arrays;

3.1 toString方法 

public static String toString(Type[] arr),返回指定数组内容的字符串表示形式。

【示例】

int[] arr = {3, 5, 1, 7, 6, 2, 4};

// 把数组转化为字符串输出

System.out.println(Arrays.toString(arr)); // 输出:[1, 2, 3, 4, 5, 6]

3.2 equals判断

public static boolean equals(Type[] a1, Type[] a2), 判断两个数组中的内容是否相同。

【示例】

int[] arr1 = {3, 5, 1, 7, 6, 2, 4};

int[] arr2 = {3, 5, 1, 7, 6, 2};

// 判断两个数组的内容是否相同

boolean flag = Arrays.equals(arr1, arr2);

System.out.println(flag); // 输出:false

3.3 sort排序

public static void sort(Type[] arr) ,对数组中的内容进行升序排序。

【示例】

int[] arr = {3, 5, 1, 7, 6, 2, 4};

// 对数组中的内容进行升序排序

Arrays.sort(arr);

System.out.println(Arrays.toString(arr)); // 输出:[1, 2, 3, 4, 5, 6, 7]

3.4 二分法查找

public static int binarySearch(Type[] arr, Type key),查找key在数组中的索引位置。如果找到,则返回索引位置;如果没找到,则返回一个负数。

注意:在调用此调用之前,必须先对数组进行排序。

【示例】

// 排序好的数组

int[] arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

// 查找6在数组中的索引位置

int index = Arrays.binarySearch(arr, 6);

System.out.println(index);  // 输出:6

// 查找18在数组中的索引位置

index = Arrays.binarySearch(arr, 18);

System.out.println(index);  // 输出:-11,证明没找到

3.5 fill填充数组

public static void fill(Type[] a, Type val),给数组填充指定内容。

【示例】

int[] arr = new int[5];

Arrays.fill(arr, 89);

System.out.println(Arrays.toString(arr)); // 输出:[89, 89, 89, 89, 89]

3.6 数组拷贝

public static Type[] copyOf(Type[] original, Type newLength)从数组的第一个元素开始拷贝,拷贝指定长度的数组,拷贝完成返回一个新的数组。

【示例】

int[] arr = {1, 2, 3, 4, 5};

int[] newArr = Arrays.copyOf(arr, 3);

System.out.println(Arrays.toString(newArr));  // 输出:[1, 2, 3]

public static Type[] copyOfRange(Type[] original, int from, int to),从指定范围拷贝数组,拷贝完成返回一个新的数组。

【示例】

int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};

int[] newArr = Arrays.copyOfRange(arr, 2, 5);

System.out.println(Arrays.toString(newArr));   // 输出:[3, 4, 5]

4.数组知识点补充

4.1 for-each循环遍历

for each是java SE 5.0增加了一种功能很强的循环结构,可以用来一次处理数组中的每个元素(其他类型的元素集合亦可)而不必为指定下标值而分心。

这种增强的for each循环的语法格式为:

for (type element : array) {

     System.out.println(element); // 输出数组中的每一个元素

}

【示例】

public static void main(String[] args) {

    int[] arr = {1, 2, 3, 4, 5, 6};

    // 通过增强for循环遍历数组

    for(int element : arr) {

       // 依次输出数组的元素

        System.out.println(element);

    }

}

优点:语法简洁,比普通for循环的效率高。

缺点:相比较普通for循环,增强for循环无法获得数组下标。

4.2 main方法的形参

参数String[ ] args的作用就是可以在main方法运行前将参数传入main方法中。

  • 从控制台,输入编译执行命令时传参数

例如下面代码:

public static void main(String[] args) {

    System.out.println("args数组长度:" + args.length);

    // 遍历args中的每一个元素

    for(String arg : args) {

       System.out.println(arg);

    }

}

但是此时args[]并没有赋值,我们需要从控制台命令行进行赋值,就像这样:

 

  • 在Eclipse使用String[ ] args参数

在代码编辑窗口,点击鼠标右键

 

出现以下窗口,切换到(x)=Arguments窗口,输入参数,最后点击Run运行即可。

 

4.3方法的可变参数

可变参数:适用于参数个数不确定,但类型确定的情况,java把可变参数当做数组处理。

我们使用...表示可变长参数,...位于变量类型和变量名之间,前后有无空格都可以。

【示例】

public static void main(String[] args) {

    System.out.println(add(1, 2));   // 输出:3

    System.out.println(add(1, 2, 3));  // 输出:6

}

// 可变参数函数

public static int add(int a, int b, int ... arr) {

    int sum = a + b;

    for(int i = 0; i < arr.length; i++) {

       sum += arr[i];

    }

    return sum;

}

可变参数的特点:

  1. 一个方法中可变参数最多只能有一个,并且只能出现在参数列表的最后面。
  2. 调用可变参数的方法时可以给出任意个参数,在方法体中以数组的形式访问可变参数。

5.二维数组

5.1二维数组的定义

二维数组本质上是以数组作为数组元素的数组,即“数组的数组”。(通俗来讲二维数组的每一个元素又是一个一维数组)

5.2二维数组的创建

  • 创建格式一,创建等长的二维数组

语法语法:数据类型[][] 数组名 = new 数据类型[m][n];

m: 表示这个二维数组的长度。
n: 表示二维数组中每个元素的长度。

注意以下格式也可以表示二维数组:

数据类型 数组名[][] = new 数据类型[m][n];

数据类型[] 数组名[] = new 数据类型[m][n];

语法格式:数据类型[][] 数组名 = new 数据类型[m][]; 

m: 表示这个二维数组的长度。
二维数组中元素的长度没有给出,可以动态的给。

基本格式:

数据类型[][] 数组名 = new 数据类型[][]{{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};

简化格式:

数据类型[][] 数组名 = {{元素1,元素2...},{元素1,元素2...},{元素1,元素2...}};

【随堂练习】

  1. 有三个班级,第一个班级3个学生,第二个班级4个学生,第三个班级5个学生。要求通过键盘录入三个班级学生的成绩,并计算每个班级学生的的平均成绩和三个班级学生的总均成绩。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值