Java编程思想总结篇——第十六章

第十六章 数组

1 数组为什么特殊

数组与其他种类的容器之间的区别有三方面:效率、类型和保存基本类型的能力。

在Java中数组是一种效率最高的存储和随机访问对象引用序列的方式。

数组就是一个简单的线性序列,这使得元素访问非常快速。但是为这种速度所付出的代价是数组对象的大小被固定,并且在其生命周期中不可改变。

泛型的出现使得容器也具备了类型检查的能力,而自动装箱机制使容器可以与数组几乎一模一样的用于基本类型,数组的硕果仅存的优点就是效率。

数组之所以优于泛型之前的容器,就是因为可以创建一个树去持有某种基本类型,意味着可以通过编译期检查,防止插入错误类型和抽取不当类型。

2 数组是第一组对象

对象数组保存的是引用,基本类型数组保存的是值。

在声明数组时可采用“聚集初始化”方法:

int[] integers = {0, 1, 2, 3, 4};

但是如果不在声明时初始化则必须采用“动态聚集初始化”方法:

int[] integers;

integers = new int[] {0, 1, 2, 3, 4};

基本类型:数值型初始化为0,char型初始化为 (char)O,boolean型初始化为false。

对象类型:初始化为null。

3 返回一个数组

与C++不同,Java可以返回一个数组

4 多维数组

Java 1.5新增的Arrays.deepToString()方法可以将多维数组转换为可读的String。

数组中构造矩阵的每个向量都可以具有任意的长度,这被称为粗糙数组。

如:

a[][] = {{{}, {0} }, {{0,0}, {0,0,0}, {0,0,0,0,0}},{{0}} }

自动包装机制对数组初始化器也起作用。

5 数组与范型

数组和泛型不能很好的结合,因为数组必须知道它所持有的确切类型,以强制保证类型安全。

不能实例化具有泛型参数类型的数组:

Peel[] peels = new Peel[10]; //erro

如果确定将来不会向上转型,并且需求相对简单,那么可以创建泛型数组。但是泛型容器总是比泛型数组更好的选择。

List[] ls;
List[] la = new List[20];
ls = (List[])la;
ls[0] = new ArrayList();
//erro
//ls[1] = new ArrayList();

Object[] objects = ls;
objects[1] = new ArrayList();

6 创建测试数据

Java标准类库Arrays有一个作用十分有限的fill()方法,只能用同一个值填充各个位置,针对对象而言,就是复制同一个引用进行填充,还可以只填充数组的某个区域:

填充数组,如

double[] a = new double[5];

Arrays.fill(a,1.0);

String[] b = new String[7];

Arrays.fill(b,3,5,"Feynman");

7 Arrays实用功能

六个基本功能:

  1. equals() 比较数组是否相等
  2. fill() 填充数据
  3. sort() 排序
  4. binarySearch() 在排序数组中查找
  5. hashCode() 产生散列码
  6. List( ) 转为List容器

复制数组:

Java标准类库提供static方法System.arraycopy(),用它复制数组比用for循环复制快很多。

System.arraycopy(Object src, int srcPosition, Object dest, int destPosition, int length);

基本类型数组与对象数组都可以复制。如果复制对象数组,只是复制了对象的引用——而不是对象本身的拷贝,这被称为浅复制。System.arraycopy()不会执行自动包装盒自动拆包,两个数组必须具有相同的确切类型。

数组比较:

想到条件:元素个数相等,元素内容相等。

Arrays类提供了静态equals()方法,用来比较整个数组。数组相等的条件是元素个数必须相等,并且对应位置的元素也相等,通过对每一个元素使用equals()方法来作比较。

使用Arrays.deepEquals()可以比较多维数组。

使用静态方法Arrays.sort()用语对数组进行排序。

数组元素比较:

Java有两种方式来提供比较功能:

1.实现java.lang.Comparable接口,覆写其compareTo()方法。如果没有实现Comparable接口,调用sort()会抛出ClassCastException异常。

2.不可能总改变类的接口或者修改其代码,更灵活的是 需要比较时,创建一个实现Comparable接口的类。这是策略设计模式的一个应用实例。这个类有两个方法compare()和equals()方法。不一定要实现equals()方法,因为它间接的继承自Object的equals()方法。

数组排序:

Collections类包含一个reverseOrder()静态方法可以产生一个Comparator,它可以翻转自然的排序顺序。

String的排序算法依据词典编排顺序排序,所以大写字母开头的词都放在前面,然后是小写字母。

如果想一起排序,就String.CASE_INSENSITIVE_ORDER。如:Arrays.sort(sa, String.CASE_INSENSITIVE_ORDER);

在已排序数组中查找:

对于已经排序好的数组,使用Arrays.binarySearch()快速查找,必须是对排序好的数组才可使用。

如果要对未排序的数组使用binarySearch()将产生不可预料的结果(可能指没找到元素的返回情况)。

如果在数组中找到要找的值,返回该值所在位置的索引,如果未找到,则返回负值,其计算方式是 -(插入点)-1,插入点指第一个大于该元素的数所在的位置。

如 对数组{1,2,4,5}查找3,那么返回 - 2-1 = -3

如果需要对没有重复元素的数组排序可以使用TreeSet(保持排序顺序),或者LinkedHashSet(保持插入顺序)。这些类会自动处理所有细节。除非他们成为程序性能的瓶颈,否则不需要自己维护数组。

如果使用Comparator排序了某个对象数组,在使用binarySearch()时必须提供同样的Comparator。

8 总结

使用新版本的Java时,优选容器而不是数组。只有在已证明性能成为问题(并且切换到数组对性能提高有所帮助)时,才应该将程序重构为使用数组。

你可能感兴趣的:(JAVA,Java编程思想学习笔记)