【Java编程】编程基础--数组结构1

目录

【创建数组】

语法

基本技巧

举例

【数组元素】

有效的下标

优化

【数组变量赋值】

【复制数组】

1. System.arraycopy()

2. Arrays.copyOf()

3. Arrays.copyOfRange()

4. Object.clone()

5. for循环

6. System.arraycopy()、Arrays.copyOf()、Arrays.copyOfRange()之间的区别


数据可以存放在变量里,每一个变量有一个名字有一个类型,还有它的生存空间

如果我们需要保存一些相同类型、相似含义、相同生存空间的数据,我们可以用数组来保存这些数据,而不是用很多个独立的变量

数组是长度固定的数据结构,用来存放指定的类型的数据。

一个数组里可以有很多个数据,所有的数据的类型都是相同的。

一维数组相当于高中数学中的数列,二维数组中相当于线性代数中的矩阵。


【创建数组】

语法

动态初始化: 数据类型[] 数组名 = new 数组元素类型[数组长度] ;

静态初始化: 数据类型[] 数组名 = 初值表 };

基本技巧

数组定义、数组元素初始化:在声明一个数组的同时对数组的每个元素进行赋值。

数组遍历、

数组元素输出等。

举例

如何写一个程序计算用户输入的数字的平均数,并输出所有大于平均数的数。
        Scanner in = new Scanner(System.in);int num = in.nextInt();int sum = 0;int cnt = 0;int[] numbers = new int[100];      // 1.创建一个数组numbers//计算平均值  (输入-1 结尾)while (num != -1)   { numbers[cnt] = num;            // 2.给数组赋值sum += num;cnt++;num = in.nextInt();}if (cnt > 0) {System.out.printf("%.2f", (double) sum / cnt);}for (int i = 0; i < cnt; i++) {      // 3.遍历数组元素,逐个判断if (numbers[i] > (double) sum / cnt) {System.out.println("\t 大于平均数:"+ numbers[i]);}}

史博:【Java编程】程序结构--循环1(while...和do...while)0 赞同 · 0 评论文章正在上传…重新上传取消

本题是在史博:【Java编程】程序结构--循环1(while...和do...while)问题4 “算平均数”上的拓展。除了计算平均值

外,还要将读到的满足“大于平均数”条件的 num 打印出来。就要先用数组变量将其记录,共增加三步:

1. 定义数组:创建 一个数组变量(100个int元素大小的数组交给数组变量 numbers;

2. 给数组赋值,将每次输入的数存进去;

3. 遍历数组里面每个元素,if 逐一判断和平均值的大小;


【数组元素】

每个元素都是同一种类型,索引或下表是从 0 开始的。

通过索引访问,索引从 0 开始,所以索引值从 0 到 数组变量.length-1。即数组的元素个数 -1。

数组变量 myList

有效的下标

编译器不会检查有效下标,但运行的时候出现无效下标,程序就会终止。比如:数组myList一共100个元素,

myList[-1]=10;

myList[101]=10;

就属于无效下标。

优化

上面例子中的代码也存在安全隐患。因为输入的数据可能会超过100个,numbers的空间可能不够。

tips:
1. 数组一旦创建,不能改变大小;
2. 元素个数必须给出;
3. 元素个数可以是变量;

解决方法是将个数设置为变量。先让用户输入有多少个数字要计算。

1. 第1个数字是用户告诉我们他需要输入多少个数,正式序列从第2个起;

2. 超出个数以外的数字将无法被计算在内;(把while循环改成for循环,因为之前不知道要输入多少个数,用-1作为开关。现在用户告诉了多少个数,数组的长度固定了,超出的部分不会进数组计算);

3. 输入的数字要和总数一致;

4. l=a.length()这种使用方式使得代码具有可扩展性;

Scanner in = new Scanner(System.in);     int cnt = in.nextInt();         //第1个数要求用户输入的是总个数int sum = 0;if( cnt > 0 ){int[] numbers = new int[cnt];   // 扩展性,元素个数可以是变量for (int i =0; i (double) sum / cnt) {System.out.println("\t 大于平均数:"+ numbers[i]);}}}

用GPT搜索一组代码,用户直接输入数字就可以计算了。不用规定第一个第二个输什么。

        Scanner scanner = new Scanner(System.in);System.out.print("请输入一组数,以空格分隔:");String input = scanner.nextLine();String[] numStrs = input.split(" "); // 将字符串中的数字分离出来double sum = 0;for (String numStr : numStrs) { // 将数字字符串转换为double类型并求和sum += Double.parseDouble(numStr);}double average = sum / numStrs.length; // 求平均数System.out.println("平均数为:" + average);System.out.print("大于平均数的数为:");for (String numStr : numStrs) {double num = Double.parseDouble(numStr);if (num > average) {System.out.print(num);

【数组变量赋值】

int[] a = new int[10];
a[0] =5;
int[] b= a;
b[0]=16;
System.out.println(a[0]);   //16

1. 数组变量 int[] a 是数组的管理者而非所有者。数组必须创建出来,然后交给数组变量来管理。因此,数组变量里面没有数据,它只是管着放在某个别的地方的数组(普通变量 int a 是数据的所有者,拥有这个数据);

2. 数组变量之间的赋值是管理权限的赋予。变量共同管理同一个数组;

3. 数组变量之间的比较是判断是否管理同一个数组;

        int[] a = {1,2,3,4,5};int[] b = a;System.out.println(a==b);   // true 

int[] a 和 int[] b 管理的是同一个数组,所以结果为true。如果做如下改动,结果为false。

        int[] a = {1,2,3,4,5};int[] b = {1,2,3,4,5};System.out.println(a==b);  // false 

由此可见,int[] b = a 只是管理同一个数组,并无法做到将一个数组里的每个元素拷贝给目标数组。


【复制数组】

数组复制的常用方法有四种:

1. for循环效率最低 ;2. System.arraycopy() 效率最高;3. Arrays.copyOf() ;4. Object.clone()

1. System.arraycopy()

功能

可以将一个数组的全部内容复制到另一个数组中,也可以将部分内容复制到另一个数组中。

语法

System.arraycopy(Object src,  int srcPos, Object dest, int destPos, int length)
/** @param      src      the source array.                       // 源数组* @param      srcPos   starting position in the source array.  // 源数组的起始索引* @param      dest     the destination array.                  // 目标数组* @param      destPos  starting position in the destination data. // 目标数组的起始索引 * @param      length   the number of array elements to be copied.  // 复制的元素数量
*/

它会将源数组从索引 srcPos 开始的 length 个元素复制到目标数组 dest 的索引 destPos 处。

举例

// 将 src 数组的一部分复制到 dest 数组中
int[] arr0 = { 1, 2, 3, 4, 5 };
int[] arr2 = { 2, 3, 4, 8, 9 };
System.arraycopy(arr, 1, arr2, 0, 3);

最后的结果 int[] arr2 ={2,3,4,8,9},就是:2,3,4(加入的) + 8,9(原来的)。

// 将 src 数组的全部内容复制到 dest 数组中
int[] src = {1, 2, 3, 4, 5};
int[] dest = new int[5];
System.arraycopy(src, 0, dest, 0, src.length);

将 src 数组中的元素复制到 dest 数组中,src 和 dest 必须是同类型数组,否则会抛出 ArrayStoreException。

2. Arrays.copyOf()

功能

将一个数组的全部内容复制到一个新数组中。如果需要部分复制得用 Arrays.copyOfRange。

语法

Arrays.copyOf(T[] original, int newLength)T[] original :源数组;
int newLength:新数组的长度

举例

 // 将 src 数组的全部内容复制到 dest 数组中int[] src = {1, 2, 3, 4, 5};int[] dest = Arrays.copyOf(src, src.length);

3. Arrays.copyOfRange()

功能

主要用于对一个已有的数组进行截取复制,复制出一个左闭右开区间的数组。

语法

public static int[] copyOfRange(int[] original, int from, int to )    * @param original the array from which a range is to be copied       //源数组 * @param from the initial index of the range to be copied, inclusive // 截取的起始位置,包含* @param to the final index of the range to be copied, exclusive.    // 传入复制的结束位置,不包含

一般数组.length-1表示数组的最后末尾,但这里这个方法是不包括第三个参数,并且可以第三个参数可以位于数组之外,使用的时候要注意。

4. Object.clone()

newObject=someObject.clone();

这个语句讲someObject地址复制到一个新的内存地址,之后将新地址的引用赋值给了newObject。

5. for循环

6. System.arraycopy()、Arrays.copyOf()、Arrays.copyOfRange()之间的区别

a. 复制过程不同

System.arraycopy() 方法在底层使用了本地平台的系统调用,它比 Arrays.copyOf() 方法和 Arrays.copyRange() 方法复制数组的速度更快
Arrays.copyOf() 方法和 Arrays.copyRange() 方法则是使用了 Java 代码实现的复制算法。它们的速度相对较慢,但是由于没有底层的系统调用,它们的可移植性更好

b. 适用场景不同

System.arraycopy() 方法适用于需要高效复制数组的场景,例如在算法和数据结构中需要处理大量的数组。
Arrays.copyOf() 方法适用于需要复制数组并扩展长度的场景,例如需要创建一个新数组,同时保留原数组的值。
Arrays.copyRange() 方法适用于需要对数组中的每个元素进行增量复制的场景,例如实现矩阵加法、矩阵乘法等运算。

c. 目标数组自动扩容

System.arraycopy() 方法不会自动扩容目标数组,如目标数组长度不够ArrayIndexOutOfBoundsException 异常。Arrays.copyRange() 方法与 System.arraycopy() 方法相同,也不会自动扩容目标数组。
Arrays.copyOf() 方法会自动创建一个新数组,返回长度和参数指定的长度相同,但是如果目标数组长度不够,也会自动扩容并复制数组元素 Array.copy(E[] e,newLength)。

d. 能否复制多维数组

System.arraycopy() 方法可以复制多维数组,但是需要使用嵌套循环来复制每个维度。
Arrays.copyOf() 方法和 Arrays.copyRange() 方法只能复制一维数组。

把二维数组复制到一维数组的例子:

        public static void main(String[] args) {// 创建源数组int[][] arrays = new int[3][3];// 遍历二维数组赋初值for (int i = 0; i < arrays.length; i++) {for (int j = 0; j < arrays[i].length; j++) {// 每个数为1-100的随机数arrays[i][j] = (int) (Math.random() * 100);}}for (int[] arr : arrays) {System.out.println(Arrays.toString(arr));}// 创建目标数组int[] a = new int[arrays.length * arrays[0].length];for (int i = 0; i < arrays.length; i++) {// 将二维数组的每一行复制到目标数组中System.arraycopy(arrays[i], 0, a, i * arrays[i].length, arrays[i].length);}System.out.println("-------------------------------");System.out.println(Arrays.toString(a));

e. 处理目标数组长度不足的方式不同

System.arraycopy()直接将源数组中的值复制到目标数组,如目标长度不够ArrayIndexOutOfBoundsException。
Arrays.copyOf() 方法和 Arrays.copyRange() 方法则会创建一个新的数组,长度与指定的长度相同或更大,并将源数组的值复制到新数组中。如果源数组长度不足,则使用默认值作为补充。int默认0,char默认''(空字符)。

public static void main(String[] args) {int[] arr = new int[] {1,3,5,7,9};int[] copyArr = new int[9];copyArr = Arrays.copyOf(arr, 9);System.out.println(Arrays.toString(copyArr));

输出结果:[1, 3, 5, 7, 9, 0, 0, 0, 0]

public static void main(String[] args) {int[] arr = new int[] {1,3,5,7,9};int[] copyArr = new int[9];copyArr = Arrays.copyOfRange(arr, 3, 9);System.out.println(Arrays.toString(copyArr));
}

输出结果:[7, 9, 0, 0, 0, 0]

f. 其他还有返回值不同、功能参数不同、内部实现方式不同、参数个数不同。菜鸟我还不太理解,就不写了。

另外,System.arraycopy可以实现自己到自己复制:
int[] arr ={0,1,2,3,4,5,6};
System.arraycopy(arr,0,arr,3,3);
从自身从0开始取三个,放到自身下标为3开始的位置放入3个数据。
则结果为:{0,1,2,0,1,2,6};

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部