数组的特殊性
数组区别于类容器在于: 效率,类型和保存基本类型的能力.
效率: 数组是线性序列,存储空间大小被固定, 则存储读取效率很高.
类型和保存类型的能力: 数组存储具体的类型, 则它在编译期间就会进行检查类型是否正确.
数组是第一级对象
无论使用哪种类型的数组, 数组标识符其实只是一个引用, 指向在堆中创建的一个真实对象, 这个数组对象用以保存指向其他对象的引用.
以下是数组的一些基本操作:
import java.util.*;
class BerylliumSphere {
private static long counter;
private final long id = counter++;
public String toString() { return "Sphere " + id; }
}
public class ArrayOptions {
public static void print(Object o) {
System.out.println(o);
}
public static void main(String[] args) {
BerylliumSphere[] a;
BerylliumSphere[] b = new BerylliumSphere[5];
print("b: " + Arrays.toString(b));
BerylliumSphere[] c = new BerylliumSphere[4];
for (int i = 0; i < c.length; i++) {
if (c[i] == null) {
c[i] = new BerylliumSphere();
}
}
BerylliumSphere[] d = {
new BerylliumSphere(),
new BerylliumSphere(),
new BerylliumSphere()
};
a = new BerylliumSphere[] {
new BerylliumSphere(), new BerylliumSphere()
};
print("a.length = " + a.length);
print("b.length = " + b.length);
print("c.length = " + c.length);
print("d.length = " + d.length);
a = d;
print("a.length = " + a.length);
int[] e;
int[] f = new int[5];
print("f: " + Arrays.toString(f));
int[] g = new int[4];
for (int i = 0; i < g.length; i++) {
g[i] = i * i;
}
int[] h = {11, 47, 93};
print("f.length: " + f.length);
print("g.length: " + g.length);
print("h.length: " + h.length);
e = h;
print("e.length: " + e.length);
e = new int[] {1, 2};
print("e.length: " + e.length);
}
}
我们可以返回一个数组, 即将数组当做一个对象即可. 对于C/C++来说, 是无法做到的, 它们只能返回一个指针.
针对多维数组来说, 我们需要Arrays.deepToString()来进行显示:
import java.util.*;
public class ThreeDWithNew {
public static void main(String[] args) {
int[][][] a = new int[2][2][4];
// [[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]]]
System.out.println(Arrays.deepToString(a));
// [[[I@628b4796, [[I@2608fb65]
System.out.println(Arrays.toString(a));
}
}
数组与泛型
我们无法实例化具有参数化类型的数组:
Peel<Banana>[] peel = new Peel<>[10];
这里, 由于擦除的存在, Banana会擦除为Object类型. 但我们可以对Peel进行泛型处理:
import java.util.Arrays;
public class Test {
public static <T> T[] f(T[] arg) {
return arg;
}
public static void main(String[] args) {
Integer[] ints = {1, 2, 3};
Integer[] ints2 = Test.<Integer>f(ints);
System.out.println(Arrays.toString(ints2));
}
}
创建测试数据
1. 使用Arrays.fill()
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] ints = new int[10];
Arrays.fill(ints, 1);
// [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
System.out.println(Arrays.toString(ints));
}
}
2. 将数据生成器和数组结合起来
import java.util.*;
interface Generator<T> {
T next();
}
class CountingGenerator {
public static class Boolean implements Generator<java.lang.Boolean> {
private boolean value = false;
public java.lang.Boolean next() {
value = !value;
return value;
}
}
public static class Byte implements Generator<java.lang.Byte> {
private byte value = 0;
public java.lang.Byte next() {
return value++;
}
}
static char[] chars = ("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
public static class Charater implements Generator<java.lang.Character> {
int index = -1;
public java.lang.Character next() {
index = (index + 1) % chars.length;
return chars[index];
}
}
public static class String implements Generator<java.lang.String> {
private int length = 7;
Generator<java.lang.Character> cg = new Charater();
public String() {}
public java.lang.String next() {
char[] buf = new char[length];
for (int i = 0; i < length; i++) {
buf[i] = cg.next();
}
return new java.lang.String(buf);
}
}
public static class Short implements Generator<java.lang.Short> {
private short value = 0;
public java.lang.Short next() {
return value++;
}
}
public static class Integer implements Generator<java.lang.Integer> {
private int value = 0;
public java.lang.Integer next() {
return value++;
}
}
public static class Long implements Generator<java.lang.Long> {
private long value = 0;
public java.lang.Long next() {
return value++;
}
}
public static class Float implements Generator<java.lang.Float> {
private float value = 0;
public java.lang.Float next() {
return value++;
}
}
public static class Double implements Generator<java.lang.Double> {
private double value = 0;
public java.lang.Double next() {
return value++;
}
}
}
public class GeneratorsTest {
public static int size = 10;
public static void test(Class<?> surroundingClass) {
for (Class<?> type: surroundingClass.getClasses()) {
System.out.print(type.getSimpleName() + ": ");
try {
Generator<?> g = (Generator<?>)type.newInstance();
for (int i = 0; i < size; i++) {
System.out.print(g.next() + " ");
}
System.out.println();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
test(CountingGenerator.class);
}
}
3. 从Generator中创建数组
使用任意的Generator来产生Object子类型的数组:
import java.util.*;
class CollectionData<T> extends ArrayList<T> {
public CollectionData(Generator<T> gen, int quantity) {
for (int i = 0; i < quantity; i++) {
add(gen.next());
}
}
public static <T> CollectionData<T> list(Generator<T> gen, int quantity) {
return new CollectionData<>(gen, quantity);
}
}
class Generated {
public static <T> T[] array(T[] a, Generator<T> gen) {
return new CollectionData<T>(gen, a.length).toArray(a);
}
@SuppressWarnings("unchecked")
public static <T> T[] array(Class<T> type, Generator<T> gen, int size) {
T[] a = (T[])java.lang.reflect.Array.newInstance(type, size);
return new CollectionData<T>(gen, size).toArray(a);
}
}
public class TestGenerated {
public static void main(String[] args) {
Integer[] a = {9, 8, 7, 6};
// [9, 8, 7, 6]
System.out.println(Arrays.toString(a));
a = Generated.array(a, new CountingGenerator.Integer());
// [0, 1, 2, 3]
System.out.println(Arrays.toString(a));
Integer[] b = Generated.array(Integer.class, new CountingGenerator.Integer(), 15);
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
System.out.println(Arrays.toString(b));
}
}
Arrays实用功能
1. 复制数组
使用System.arraycopy来进行数组的复制.
import java.util.*;
public class CopyingArrays {
public static void print(Object o) {
System.out.println(o);
}
public static void main(String[] args) {
int[] i = new int[7];
int[] j = new int[10];
Arrays.fill(i, 47);
Arrays.fill(j, 99);
print("i = " + Arrays.toString(i));
print("j = " + Arrays.toString(j));
System.arraycopy(i, 0, j, 0, i.length);
print("j = " + Arrays.toString(j));
int[] k = new int[5];
Arrays.fill(k, 10);
System.arraycopy(i, 0, k, 0, k.length);
Arrays.fill(k, 103);
System.arraycopy(k, 0, i, 0, k.length);
print("i = " + Arrays.toString(i));
Integer[] u = new Integer[10];
Integer[] v = new Integer[5];
Arrays.fill(u, new Integer(47));
Arrays.fill(v, new Integer(99));
print("u = " + Arrays.toString(u));
print("v = " + Arrays.toString(v));
System.arraycopy(v, 0, u, u.length / 2, v.length);
print("u = " + Arrays.toString(u));
}
}
2. 数组的比较
使用equals来比较.
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] a = new int[10];
int[] b = new int[10];
int[] c = new int[5];
System.out.println(Arrays.equals(a, b));
System.out.println(Arrays.equals(a, c));
}
}
3. 数组元素的比较
实现Comparable接口即可.
import java.util.*;
class CompType implements Comparable<CompType> {
public int i;
CompType(int i) {
this.i = i;
}
public int compareTo(CompType rv) {
return (i < rv.i ? -1 : (i == rv.i ? 0: 1));
}
}
public class Test {
public static void main(String[] args) {
CompType[] a = {
new CompType(2),
new CompType(4),
new CompType(3),
new CompType(1),
new CompType(5)
};
Arrays.sort(a);
for (int i = 0; i < a.length; i++) {
System.out.print(a[i].i + " ");
}
}
}