码迷,mamicode.com
首页 > 编程语言 > 详细

Java数组

时间:2018-10-12 17:49:04      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:eps   elf   sap   acm   ssg   wap   建立   ade   DDM   

目录

1. 数组的介绍

什么是数组?顾名思义,就是用来存储一组数据的一种数据结构。

数组可以存储多个数据,但是只能是相同类型的数据。每个数组元素存放一个数据,我们可以通过数组的索引去访问相应的元素。数组的索引从0开始,则最后一个数组元素的索引是(数组长度-1)

因为Java是面向对象的语言,而类与类之间可以支持继承关系。故这样可能产生一个数组里可以存放”多种数据类型“的假象。

例如一个存放水果的数组,那么我们就只能往里面存放”水果“这个类型的数据——意思就是,我们不单单可以存”水果“,我们还能往数组里面存放”西瓜“、”苹果“、”柚子“等水果。

为什么呢?因为”西瓜“、”苹果“、”柚子“,它们都继承于父类”水果“,都是属于水果类型的。

2. 数组的初始化

Java语言中数组必须先初始化,然后才可以使用。所谓初始化,就是为数组的数组元素分配内存空间,并为每个数组元素赋初值。

那么能不能只分配内存空间,而不赋初始值呢?答案是不能。因为一旦为数组元素分配了内存空间,那么每个内存空间里存储的内容就是该数组元素的值。

初始值的获得方式有两种方式:

2.1 静态初始化

静态初始化:由程序员显示指定每个数组元素的初始值,由系统决定数组长度。静态初始化的语法格式如下:

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

2.2 动态初始化

动态初始化:程序员只指定数组长度,由系统为数组元素分配初始值。动态初始化的语法格式如下:

int[] arr = new int[5];

注意:不要在数组初始化时既指定数组长度,又为每个数组元素分配初始值。

3. 数组的实例

public class TestArray {
    public static void main(String[] args) {
        // 创建一个double类型的数组
        double[] myList = { 1.9, 2.9, 3.4, 3.5 };

        // 传统for循环打印数组元素内容
        for (int i = 0; i < myList.length; i++) {
            System.out.println(myList[i] + " ");
        }

        // foreach循环打印数组元素内容
        // 在 foreach迭代数组元素时候,并不能改变元素数组的值,因此不要对循环变量进行赋值
        for (double d : myList) {
            System.out.println(d);
        }
        
        // 计算所有元素的总和
        double total = 0;
        for (int i = 0; i < myList.length; i++) {
            total += myList[i];
        }
        System.out.println("Total is " + total);
        
        // 查找最大元素
        double max = myList[0];
        for (int i = 1; i < myList.length; i++) {
            if (myList[i] > max)
                max = myList[i];
        }
        System.out.println("Max is " + max);
    }
}

4. 深入数组

4.1 内存中的数组

数组是一种引用数据类型,数组引用变量只是一个引用。这个引用变量可以指向任何有效的内存,只有当该引用指向有效内存后,才可通过该数组变量来访问数组元素。

实际的数组对象其实是被存储在堆内存中。而引用该数组对象的数组引用变量通常存储在栈中。数组在内存中的存储示意图如下图所示。

技术分享图片

图1 数组在内存中的存储示意图

那么,为什么数组要分两种形式来存放呢?

因为当一个方法执行时, 每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁。因此,所有在方法中定义的局部变量都是存放在栈内存中的。

在程序中创建一个对象时,这个对象将会被保存到运行时数据区(堆)中,以便反复利用(因为创建对象的成本比较高)。堆内存中的对象不会随着方法的结束而销毁,当方法结束后,该对象还可能被另外一个引用变量所引用。

当一个对象没有任何引用变量引用它时,系统的垃圾回收器才会在合适的时候回收它(也可以将该数组变量赋为null,切断了呃数组引用变量和实际数组之间的引用关系)。

只要类型相互兼容,就可以让一个数组变量指向另一个实际的数组。

但,这种操作可能会让人产生数组的长度可变的错觉,如下代码所示。

public class test {
    public static void main(String[] args) {
        
        // 定义并初始化数组,使用动态初始化
        int[] a = new int[4];
        // 定义并初始化数组,使用静态初始化
        int[] b = { 5, 7, 20 };
        // 输出a数组的长度4
        System.out.println("b数组的长度为:" + a.length);

        // 循环输出a数组的元素
        for (int arr : a) {
            System.out.println(arr);
        }
        // 循环输出b数组的元素
        for (int arr2 : b) {
            System.out.println(arr2);
        }
        // 因为a是int[]类型,b也是int[]类型,所以可以将b的值赋给a。
        // 也就是让b引用指向a引用指向的数组
        a = b;
        // 再次输出a数组的长度3
        System.out.println("a数组的长度为:" + a.length);
    }
}

运行如上代码,我们可以看到,a数组最开始的长度为4,当b引用变量指向a数组时,长度变成了3。这会误让人以为a数组长度变成了3。我们必须始终牢记数组在内存中的存储方式:**定义并初始化一个数组时,内存中会分配两个空间,一个存放数组的引用变量(栈),而另一个存放数组的本身(堆)。上诉代码的内存图示见图2。

技术分享图片

图2 让a引用指向b所指向数组后的存储示意图

通过图示分析,我们可以得知,在a没有指向b数组时,a数组的长度为4。当执行代码b=a后,实际上就变成了a、b引用变量同时指向b数组,故打印出来a指向数组的长度为3,也就是b数组的长度。而原来的a数组失去了引用,变成了垃圾,只有等待垃圾回收机制来回收它——并且在此之前它的长度不会改变,直到它彻底消失。

5. 多维数组

多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组,例如:

String str[][] = new String[3][4];

5.1 多维数组的动态初始化(以二维数组为例)

直接为每一维分配空间,格式如下:

type arrayName = new type[arraylenght1][arraylenght2];

定义的类型可以为基本数据类型复合数据类型。arraylenght1 和 arraylenght2 必须为正整数,arraylenght1 为行数,arraylenght2 为列数

例如:

int a[][] = new int[2][3];

解析:二维数组 a 可以看成一个两行三列的数组。

从最高维开始,分别为每一维分配空间,例如:

String s[][] = new String[2][]; 
s[0] = new String[2]; 
s[1] = new String[3];
s[0][0] = new String("Good");
s[0][1] = new String("Luck");
s[1][0] = new String("to"); 
s[1][1] = new String("you"); 
s[1][2] = new String("!");

解析:s[0]=new String[2]s[1]=new String[3] 是为最高维分配引用空间,也就是为最高维限制其能保存数据的最长的长度,然后再为其每个数组元素单独分配空间 s0=new String("Good") 等操作。

6. Arrays类

java.util.Arrays 类能方便地操作数组,它提供的所有方法都是静态的。

具有以下功能:

  • 给数组赋值:通过fill 方法。
  • 对数组排序:通过sort 方法,按升序。
  • 比较数组:通过 equals 方法比较数组中元素值是否相等。
  • 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作。

示例代码如下:

import java.util.Arrays;

public class ArraysTest {
    public static void main(String[] args) {
        // 定义一个一维数组
        int[] arr = { 22, 47, 1, 68, 35 };
        // 使用sort()方法对数组arr[]进行升序排序
        Arrays.sort(arr);
        System.out.println("打印出sort()方法排序后的数组:");
        for (int i : arr) {
            System.out.println(i);
        }
        System.out.println("=========================");
        // 使用二分法查询key值在数组中的索引,如果不存在则返回负数。
        // 但是调用该方法前,必须要对数组进行升序排序,这样才能得到正确的结果
        System.out.println("该key在数组的索引是:" + Arrays.binarySearch(arr, 47));
        System.out.println("=========================");
        int[] b = Arrays.copyOf(arr, 6);
        // 使用Arrays.copyof()复制的数组,如果指定的长度比原数组短
        // 则只复制指定长度数组;反之,多出来的长度则以0(int默认填充类型)填充
        for (int i : b) {
            System.out.println(i);
        }
        System.out.println("=========================");
        // 因为b数组长度比arr数组长度长,而且元素也并不相同,所以下面输出false
        System.out.println(Arrays.equals(arr, b));
        System.out.println("=========================");
        // 将arr数组的第3个元素(包括)到第5个元素(不包括)赋值为88
        Arrays.fill(arr, 2,4,88);
        // Arrays.toString()将一个数组转换成一个字符串。
        System.out.println(Arrays.toString(arr));
    }
}

参考资料:

Java数组

标签:eps   elf   sap   acm   ssg   wap   建立   ade   DDM   

原文地址:https://www.cnblogs.com/smallmin/p/9777036.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!