第十六章 数组

感觉这一章有点散,还是来说一下需要注意的点吧。

一、数组知识点

1、数组的初始化方式

①Integer[] array = {1, 2, 3};
②Integer[] array = new Integer[10];
③Integer[] array = new Integer[]{1,2,3};

数组分配空间,但是没有初始化,就是默认0值。

2、数组与容器的不同点

class Fruit {}
class Apple extends Fruit {}

Fruit[] f = new Apple[10];
List<Fruit> l = new ArrayList<Apple>();\\Error

 数组进行这样的向上转型是合法的,而List这样转型不合法,因为List<Fruit>与ArrayList<Apple>根本不是子类与父类的关系。

3、数组是最高效的存储和随机访问对象引用的方式

4、length指的是数组的大小,而不是实际保存了多少元素。

5、数组中的每一维都可以有不同的长度

import java.util.Arrays;

public class Demo1 {

    public static void main(String[] args) {
        
        Integer[][] array = new Integer[4][];
        for(int i = 0; i < array.length; i++) {
            array[i] = new Integer[i+1];
            System.out.println(Arrays.toString(array[i]));
        }
        System.out.println(Arrays.deepToString(array));
    }

}

 输出结果:

[null]
[null, null]
[null, null, null]
[null, null, null, null]
[[null], [null, null], [null, null, null], [null, null, null, null]]

结果分析:Arrays类有创建数组可打印形式的静态方法。

Arrays.toString()创建一维数组的可打印形式。

Arrays.deepToString()创建多维数组的可打印形式。

二、Arrays类的实用方法

1、示例一:填充复制数组

mport java.util.Arrays;

class Apple{}
public class Demo2 {

    public static void main(String[] args) {
        Apple[] apple = new Apple[3];
        Arrays.fill(apple, new Apple());
        System.out.println(Arrays.toString(apple));
        Integer[] a1 = new Integer[5];
        Arrays.fill(a1, 88);
        
        Integer[] a2 = new Integer[10];
        Arrays.fill(a2, 33);
        System.arraycopy(a1, 0, a2, 1, a1.length);
        System.out.println(Arrays.toString(a2));
        
    }

}

 输出结果:

[arrays.Apple@edf4efb, arrays.Apple@edf4efb, arrays.Apple@edf4efb]
[33, 88, 88, 88, 88, 88, 33, 33, 33, 33]

结果分析:

fill():填充数组,从结果可以看出,填充对象时,是将同一对象的引用分配给每个元素。

System.arraycopy():复制数组,效率高。

2、示例二:数组的比较

import java.util.Arrays;

public class Demo3 {

    public static void main(String[] args) {
        int[] a1 = new int[5];
        int[] a2 = new int[10];
        int[] a3 = new int[5];
        Arrays.fill(a1, 12);
        System.arraycopy(a1, 0, a2, 0, a1.length);
        Arrays.fill(a3, 12);
        System.out.println("Arrays.equals(a1,a2): " + Arrays.equals(a1,a2));
        System.out.println("Arrays.equals(a1,a3): " + Arrays.equals(a1,a3));
        String[] s1 = new String[2];
        Arrays.fill(s1, "Hi");
        String[] s2 = {new String("Hi"), new String("Hi")};
        System.out.println("Arrays.equals(s1,s2): " + Arrays.equals(s1,s2));
    }

}
View Code

 输出结果:

Arrays.equals(a1,a2): false
Arrays.equals(a1,a3): true
Arrays.equals(s1,s2): true

结果分析:数组相等的条件是元素个数(length)相等,对应位置的元素也相等。数组的相等时基于内容的,一般来时,对象比较都是基于内容的。

3、示例三:元素的比较

方式一:实现java.lang.Comparable接口,使得类具有“天生”的比较能力。

方式二:创建一个实现了Comparator接口的单独类。

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

class CompType implements Comparable<CompType>{
    String name;
    int age;
    CompType(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String toString() {
        return "[name = " + name + ", " + "age = " + age + "]";
    }
    public int compareTo(CompType c) {
        return name.compareTo(c.name);
    }
}

class CompTypeComparator implements Comparator<CompType> {
    public int compare(CompType c1, CompType c2) {
        return c1.age < c2.age ? -1 : (c1.age == c2.age ? 0 : 1);
    }
}
public class Demo4 {

    public static void main(String[] args) {
        CompType[] c = new CompType[] {new CompType("Mike", 18), 
                new CompType("Susan", 17), new CompType("Liu", 19)};
        System.out.println("before sorting:");
        System.out.println(Arrays.toString(c));
        System.out.println("after sorting by name:");
        Arrays.sort(c);
        System.out.println(Arrays.toString(c));
        System.out.println("after reverse by name:");
        Arrays.sort(c, Collections.reverseOrder());
        System.out.println(Arrays.toString(c));
        System.out.println("after sorting by age:");
        Arrays.sort(c, new CompTypeComparator());
        System.out.println(Arrays.toString(c));
    }

}
View Code

 输出结果:

before sorting:
[[name = Mike, age = 18], [name = Susan, age = 17], [name = Liu, age = 19]]
after sorting by name:
[[name = Liu, age = 19], [name = Mike, age = 18], [name = Susan, age = 17]]
after reverse by name:
[[name = Susan, age = 17], [name = Mike, age = 18], [name = Liu, age = 19]]
after sorting by age:
[[name = Susan, age = 17], [name = Mike, age = 18], [name = Liu, age = 19]]

结果分析:Collections.reverseOrder()返回一个强制逆转自然顺序的比较器。

4、示例四:在已排序数组中查找

import java.util.Arrays;
import java.util.Random;

public class Demo5 {

    public static void main(String[] args) {
        Random rand = new Random(11);
        Integer[] array = new Integer[10];
        for(int i = 0; i < array.length; i++) {
            array[i] = rand.nextInt(20);
        }
        Arrays.sort(array);
        System.out.println("sorted array:");
        System.out.println(Arrays.toString(array));
        while(true) {
            int key = rand.nextInt();
            int location = Arrays.binarySearch(array, key);
            if(location >= 0) {
                System.out.println("Location of " + key + " is " + location);
                break;
            }
        }
    }

}
View Code

 输出结果:

sorted array:
[0, 7, 7, 8, 11, 13, 13, 13, 15, 18]
Location of 18 is 9

结果分析:

(1)先经过sort()排序才可以调用binarySearch(),否则结果是不确定的。

(2)binarySearch()必须和sort()使用同样的Comparator。

(3)Java标准类库针对正排序算法进行了特殊优化,针对基本类型设计“快速排序”,针对对象设计“合并排序”。

 

posted @ 2019-09-14 20:17  卑微芒果  Views(200)  Comments(0Edit  收藏  举报