【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<cnt; i++)      // while 该用 for 循环
        {
            numbers[i] = in.nextInt();  // 从用户输入的第二个nextInt()开始计算下标,下标为0
            sum += numbers[i];
        }
        System.out.printf("%.2f", (double) sum / cnt);

        for (int i = 0; i < numbers.length; i++) {      // 数组名称.length的用法 i从0开始,始终比长度小1
            if (numbers[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};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值