Java编程思想之数组

来源:互联网 发布:犀牛软件多大 编辑:程序博客网 时间:2024/05/21 14:57

前言:

这篇主要是对数组的一些深入介绍,主要包括了数组的一些实用功能(复制数组、数组排序等)。

数组为什么特殊?

数组与其它种类的容器之间的区别有三方面:效率、类型和保存基本类型的能力。在Java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序列,这使得元素的访问非常迅速。但是为这种速度所付出的代价是数组对象的大小被固定。并且在其生命周期中不可改变。
数组之所以优于泛型之前的容器,就是因为你可以创建一个数组去持有某种具体类型。这意味着你可以通过编译器检查,来防止插入错误类型和抽取不当类型。数组还可以持有基本类型。而泛型之前的容器则不能。但是有了泛型,容器就可以指定并检查它们所持有对象的类型,并且有了自动包装机制,容器看起来还能够持有基本类型。

数组是第一级对象

无论使用哪种类型的数组,数组标识符其实只是一个引用,指向在堆中创建的一个真实对象,这个(数组)对象用以保存指向其他对象的引用。只读成员length 是数组对象的一部分,表示数组可以存储多少元素。“[]”语法是访问数组对象唯一的方式。

//the way to arrays initializedInteger[] a;Integer[] b = {new Integer(1),new Integer(2),new Integer(3)};  //aggregate initialization  只能在定义处使用//Dynamic aggregate initializationa  = new Integer[]{ new Integer(1),new Integer(2)};

数组a是一个尚未初始化的局部变量,在未正确地初始化之前,编译器不允许用此引用做任何事情。对象的数组自动化初始为null,基本类型的数组如果是数值型的,就被自动初始化为0,如果是字符型的,就被自动初始化为(char)0, 如果是布尔型的,就被自动初始化为 false。

数组与泛型

通常,数组与泛型不能很好地结合。你不能实例化具有参数化类型的数组:
Peel<Banana>[] peels = new Peel<Banana>[10]; //Illegal
擦除会移除参数类型信息,而数组必须知道它们所持有的确切类型,以强制保证类型安全。

Ayyays实用功能

填充数组

Arrays.fill():只能用同一个值填充各个位置,而针对对象而言,就是复制同一个引用进行填充。

/*test Arrays.fill()*/import java.util.*;class M{    public int i = 0;    public M(int i){        this.i = i;    }    public String toString(){        return super.toString()+"--"+i;    }}public class FillMethodTest{    public static void main(String[] args){        M mo = new M(2);        M[] m = new M[10];        Arrays.fill(m,mo);        System.out.println(Arrays.toString(m));        m[1].i = 3;        System.out.println(Arrays.toString(m));    }}/*运行结果:[M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2, M@15db9742--2][M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3, M@15db9742--3]*/

可以看到当改变数组中的一个元素时,其余元素也发生了改变,但是其哈希值未发生改变。

复制数组

Java标准类库提供有static 方法System.arraycopy(), 用它复制数组比用for循环复制要快很多。以下是完整的方法签名:
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)
如果复制对象数组,只是复制了对象的引用——而不是对象本身的拷贝。这被称作浅复制。

数组的比较

数组相等的条件是元素个数必须相等,并且对应位置的元素也相等。这可以通过对每一个元素使用equals()作比较来判断。
java.util.Arrays类中
public static boolean equals(Object[] a,
Object[] a2)
以上只是重载中的一个,其余的重载了基本类型。

数组元素的比较

排序必须根据对象的实际类型执行比较操作。

Java有两种方式来提供比较功能。第一种是实现java.lang.Comparable接口,使你的类具有比较能力。此接口只有一个compareTo()方法。此方法接受另一个Object为参数,如果当前对象小于参数则返回负值,如果相等则返回零,如果当前对象大于参数则返回正值。

Java标准类库的方法Arrays.sort()提供了对传入的数组(必须实现Comparable)进行排序的功能。

另一种方法,可以创建一个实现了Comparator接口的单独的类,这个类只有compare()和equals()两个方法。然而不一定需要实现equals方法,除非有特殊的性能需要。同样可以通过将目标数组和实现了Comparator接口的类传入Arrays.sort()方法来排序。

在已排序的数组中查找

如果数组已经排好序了,就可以使用Arrays.binarySearch()执行快速查找。如果要对未排序的数组使用binarySearch(), 那么将产生不可预料的结果。
如果找到了目标,Arrays.binarySearch()产生的返回值等于或大于0。否则,它产生的负返回值,表示若要保持数组的排序状态此目标元素应该插入的位置(指元素位置)。这个负值的计算方式是: -(插入点)-1 插入点是指第一个大于了查找对象的元素在数组中的位置。如果数组中的所有元素都小于要查找的对象,“插入点”就等于a.size()。

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

容器几乎总是更好的选择。

原创粉丝点击