20、第二十一章数组

数组特性

将数组和其他类型的集合区分开来的原因有三:效率,类型,保存基本数据类型的能力。在 Java 中,使用数组存储和随机访问对象引用序列是非常高效的。数组是简单的线性序列,这使得对元素的访问变得非常快。然而这种高速也是有代价的,代价就是数组对象的大小是固定的,且在该数组的生存期内不能更改。

数组和ArrayList 之间的相似是设计者有意为之,所以在概念上,两者很容易切换。集合的功能明显多于数组。随着 Java 自动装箱技术的出现,通过集合使用基本数据类型几乎和通过数组一样简单。**数组唯一剩下的优势就是效率。**然而,当你解决一个更加普遍的问题时,数组可能限制太多,这种情形下,您可以使用集合类。

Java 提供了 Arrays.toString() 来将数组转换为可读字符串

一等对象

对象数组和基元数组在使用上是完全相同的。唯一的不同之处就是对象数组存储的是对象的引用,而基元数组则直接存储基本数据类型的值。

多维数组

Array.deepToString() 方法,这将多维数组转换成 String 类型。

Java 8 增加了 Arrays.setAll() 方法,其使用生成器来生成插入数组中的值。

泛型数组

可以参数化数组本身的类型。

class ClassParameter<T> {
    public T[] f(T[] arg) {
        return arg;
    }
}

class MethodParameter {
    public static <T> T[] f(T[] arg) {
        return arg;
    }
}

Arrays 的 fill 方法

Arrays 类包括一个普通的 fill() 方法,该方法将单个值复制到整个数组。

Arrays 的 setAll 方法

java.util.Arrays#setAll 使用一个生成器并生成不同的值,可以选择基于数组的索引元素(通过访问当前索引,生成器可以读取数组值并对其进行修改)。

数组并行

java.util.Arrays#parallelSetAll

Arrays 工具类

  • asList(): 获取任何序列或数组,并将其转换为一个 列表集合
  • copyOf():以新的长度创建现有数组的新副本。
  • copyOfRange():创建现有数组的一部分的新副本。
  • equals():比较两个数组是否相等。
  • deepEquals():多维数组的相等性比较。
  • stream():生成数组元素的流。
  • hashCode():生成数组的哈希值。
  • deepHashCode(): 多维数组的哈希值。
  • sort():排序数组
  • parallelSort():对数组进行并行排序,以提高速度。
  • binarySearch():二分查找,在已排序的数组中查找元素。
  • parallelPrefix():使用提供的函数并行累积(以获得速度)。基本上,就是数组的 reduce() 。
  • spliterator():从数组中产生一个 Spliterator
  • toString():为数组生成一个字符串表示。
  • deepToString():为多维数组生成一个字符串。对于所有基本类型和对象,所有这些方法都是重载的。

parallelPrefix 并行前缀

没有 prefix() 方法,只有 parallelPrefix()。这类似于 Stream 类中的 reduce() 方法:它对前一个元素和当前元素执行一个操作,并将结果放入当前元素位置

package arrays;

import onjava.Count;

import java.util.Arrays;

import static onjava.ArrayShow.show;

public class ParallelPrefix1 {
    public static void main(String[] args) {
        int[] nums = new Count.Pint().array(10);
        show(nums); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        System.out.println(Arrays.stream(nums).reduce(Integer::sum).getAsInt());    // 45
        Arrays.parallelPrefix(nums, Integer::sum);
        show(nums); // [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
        System.out.println(Arrays.stream(new Count.Pint().array(6)).reduce(Integer::sum).getAsInt());   // 15
    }
}

本章小结

Java为固定大小的低级数组提供了合理的支持。这种数组强调的是性能而不是灵活性

在Java的最初版本中,固定大小的低级数组是绝对必要的,这不仅是因为Java设计人员选择包含原生类型(也考虑到性能),还因为那个版本对集合的支持非常少。

在Java的后续版本中,集合支持得到了显著的改进,现在集合在除性能外的所有方面都优于数组,即使这样,集合的性能也得到了显著的改进。

所有这些问题都表明,在使用Java的最新版本进行编程时,应该“优先选择集合而不是数组”。