Java中数组数据结构的要点

19-03-14 jdon
         

1. 首先,数组是Java中的对象。它们不是像int、short或long这样的基本类,也不是具有很多方法的全功能对象,但由于它们是对象,所以它们隐式地扩展了Object,这就是为什么可以使用数组引用(例如toString())调用java.lang.object的任何方法。

2. Java中数组的另一个重要之处是,一旦创建,就不能更改数组的大小。好奇的开发人员可能会问,我们如何在Java中拥有像ArrayList这样的动态集合,可以在饱和的时候调整自身大小?好吧,扩容不像你想得那样,可以简单地增加一个数组的大小来容纳额外的元素。为了增加大小,必须创建一个新数组,并将内容从旧数组复制到新数组。尽管存在将元素从一个数组复制到另一个数组的快速方法,但它仍然是一个代价很大的操作,还会降低Java应用程序的性能。 这就是为什么初始化具有适当大小的数组或集合仍然是最好的做法之一。

3. 关于数组,第三件要知道的是它的长度属性,它告诉你数组的大小或它可以容纳多少元素。这通常也是造成混淆的原因,因为字符串有类似的length()方法,这是一个方法,而数组长度是属性,所以不再有括号。另一个增加这种混淆的是arraylist的size()方法,它也返回arraylist可以容纳多少元素。 下面是一个代码片段示例,用于查找Java中数组的长度。

int[] arrayOfInts = new int[] { 101, 102, 103, 104, 105 };

System.out.println("length of arrayOfInts is : " + arrayOfInts.length);  // print 5

在Java中循环遍历数组时,可以使用数组的长度来避免访问无效的索引,如下一个示例所示。

4.数组索引从零开始,因此第一个元素的索引为0,最后一个元素的索引为length -1。 此属性用于迭代for循环中的所有元素。

 String[] cities = new String[]{"London", "Paris", "NewYork", "HongKong", "Tokyo"};

      

for(int i=0;  i<cities.length;  i++){
           String city = cities[i];
           System.out.println("Current city is @ " + city);
       }

Output :
Current city is @ London
Current city is @ Paris
Current city is @ NewYork
Current city is @ HongKong
Current city is @ Tokyo

您可以看到,我们从0(第一个元素)开始循环,以小于长度的方式结束循环,例如length -1(最后一个元素索引)。如果尝试访问数组[长度],将获得arrayIndexOutOfBoundsException,因为最后一个索引是length -1。

 5. 正如我之前所说的,Java虚拟机将数组视为对象。数组的类型是“[elementType”,其中element type是元素的类型。例如,一个(一维)整数数组的类型为“[I”,同样,一维短数组的类型为“[S”,一维浮点数组的类型为“[F”。对于二维数组,可以得到两个“[[”,例如,二维int数组的类型为“[[i”。当您在Java中打印数组时,可以检查这一点。它打印其元素类型和哈希代码,如下所示。

 public class PrintArrayTypes{

    public static void main(String args[]) {

        // type of one dimensional array in Java
        int[] arrayOfInts = new int[] { 101, 102, 103, 104, 105 };
        System.out.println(arrayOfInts);

        short[] arrayOfShorts = new short[] { 20, 30, 40, 50, 60 };
        System.out.println(arrayOfShorts);

        float[] arrayOfFloats = new float[] { 2.0f, 3.0f, 4.0f, 5.0f, 6.0f };
        System.out.println(arrayOfFloats);

        // type of two dimensional array in Java
        int[][] arrayOfArrayOfInts = { { 1, 2, 3 }, { 10, 20, 30 },
                { 100, 200, 300 } };
        System.out.println(arrayOfArrayOfInts);

        double[][] arrayOfArrayOfDoubles = { { 2.0, 3.0 }, { 4.0, 5.0 } };
        System.out.println(arrayOfArrayOfDoubles);

    }

}

Output
<p>[I@1693b52b
<p>[S@3b5b25a1
<p>[F@5d038b78
<p>[[I@7b9a29
<p>[[D@32c5f9fe

 

6.如果关注我的上一个示例,那么您会注意到使用toString()打印数组不会产生除元素类型之外的任何有用的内容。 理想情况下,我们希望按照它们存在的顺序查看数组的元素。 我们可以重写array类的toString()方法吗?不,这不是一个选项,但不要担心我们有一个实用程序类java.util.Arrays,它包含几种方法来处理不同类型的数组。 我们可以使用Arrays类的toString()和deepToString()方法在Java中打印一维和多维数组的数组元素,如下所示。

 7. 与toString()类似,数组的equals()方法也没有用处。在大多数情况下,我们希望将数组的元素及其顺序与另一个数组及其元素进行比较,但array的equals()方法不这样做,而是引用比较,仅当两个变量都指向同一个数组对象时才返回true,如下例所示。但是不用担心,Arrays类用equals() 和deepEquals() 方法来比较Java中的一维数组和多维数组元素。您可以通过以下示例推断出相同的理解:

 public class ArrayEquality{

    public static void main(String args[]) {

       String[] cities = new String[]{"London", "Paris", "NewYork", "HongKong", "Tokyo"};
       String[] metros = new String[]{"London", "Paris", "NewYork", "HongKong", "Tokyo"};
       String[] capitals = cities;
       
       // comparing array using == operator
       System.out.println("cities == metros : " + (cities == metros));
       System.out.println("cities == capitals : " + (cities == capitals));
       
       
       // comparing array using equals() method
       System.out.println("cities.equals(metros) : " + cities.equals(metros));
       System.out.println("cities.equals(capitals) : " + cities.equals(capitals));
     

       // comparing array using Arrays.equals() method
       System.out.println("Arrays.equals(cities, metros) : " + Arrays.equals(cities, metros));
       System.out.println("Arrays.equals(cities, capitals) : " + Arrays.equals(cities, capitals));
       
    }

}

Output :
cities == metros : false
cities == capitals : true
cities.equals(metros) : false
cities.equals(capitals) : true
Arrays.equals(cities, metros) : true
Arrays.equals(cities, capitals) : true

 

您可以看到尽管元素及其顺序相同,第一条语句是假的,因为“==”运算符仅在两个变量都指向同一数组时才返回真,这是第二次相等性检查的情况。同样,equals()方法也模拟了==运算符的行为,因为数组不会重写对象的equals()方法,其默认行为是基于相同的引用来决定相等性。 Arrays.equals()是检查两个数组在Java中是否相等的正确方法。为此,你应该一直使用它。

 8. Java程序员应该习惯使用deepEquals()方法来检查两个多维数组的相等性,因为Arrays.equals()方法不执行多维比较。 以下是检查Java中多维数组相等性的示例:

 

public class MultiDimensionalArray{

    public static void main(String args[]) {

       int[][] a1 = { {2,4}, {4,6}, {8,10} };
       int[][] a2 = { {12,14}, {14,16}, {18,20} };
       int[][] a3 = { {2,4}, {4, 6}, {8,10} };
       
       // checking if two multi-dimensional array of same length but different element equal or not
       boolean result = Arrays.deepEquals(a1, a2);
       System.out.println("Does two dimensional array a1 and a2 are equal : " + result);
       
       
       // checking if two multi-dimensional array of same length, elements equal or not
       result = Arrays.deepEquals(a1, a3);
       System.out.println("Does two dimensional array a1 and a3 are equal : " + result);
       
    }

}

Output :
Does two dimensional array a1 and a2 are equal : false
Does two dimensional array a1 and a3 are equal : true

9.使用java时,你需要多次在静态数组与动态数组之间进行转换。

10. 在Java中有几种初始化数组的方法。你也可以在不初始化的情况下创建它们,在这种情况下,所有存储桶都将保持元素类型的默认值,例如,如果你创建一个空数组并且没有初始化它,则所有存储桶都将保持为零,因为这是Java中整数变量的默认值。 类似地,布尔数组默认使用false值初始化,String数组使用空值初始化。 如果您事先知道这些值,则可以在创建时初始化数组,如下所示:

 

 int[] numbers = {1, 2, 3, 4, 5}; // valid
int multipleOfThree[] = {3, 6, 9, 12, 15}; // valid 
int[] even = new int[]{2, 4, 6, 8, 10}; // valid

11. 一个额外的提示是,array与arraylist有很大的不同,后者是一个动态数组,它可以根据需要调整自身的大小。另一方面,创建后不能更改数组的大小。除了这一事实之外,这两个类之间还有几个不同之处,例如ARAYLIST是Java集合框架的一部分,但数组不是。

这是关于Java中数组数据结构的一些要点的列表。使用数组来保存相同类型的元素,例如整数、字符串或对象,但不能混合它们,例如Java数组不能同时包含整数和字符串,在编译时是错误的,但对于对象,如果编译器允许,它将在运行时抛出arraystoreException。同样,如果知道索引,数组也是用于访问元素的快速数据结构之一