第十六章 数组

 

16.1数组为什么特殊

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

数组和容器如果越界都会抛出RuntimException异常。

 

在泛型之前,其它容器类在处理对象时都会当作Object类型,数组之所以优于泛型之前的容器,创建一个数组时就限定了数组持有对象的类型,这意味着可以在编译器进行检查。

数组可以持有基本类型,泛型之前的容器则不能,但有了泛型和自动装箱,其它容器也可以持有基本类型数据,数组仅存的优点就是效率。

public class BerylliumSphere {
	public static long count;
	public final long id = count++;
	@Override
	public String toString() {
		return "BerylliumSphere [id=" + id + "]";
	}
}
public class ContainerComparison {
	public static void main(String[] args) {
		//数组保存对象
		BerylliumSphere[] spheres = new BerylliumSphere[10];
		for (int i = 0; i < 5; i++) {
			spheres[i] = new BerylliumSphere();
		}
		System.out.println(Arrays.toString(spheres));
		System.out.println(spheres[4]);
		
		//集合保存对象
		List<BerylliumSphere> phereList = new ArrayList<BerylliumSphere>();
		for (int i = 0; i < 5; i++) {
			phereList.add(new BerylliumSphere());
		}
		System.out.println(phereList);
		System.out.println(phereList.get(4));
		
		//数组保存基本类型
		int[] integers = {1,2,3,4,5};
		System.out.println(Arrays.toString(integers));
		System.out.println(integers[4]);
		
		//集合保存基本类型
		List<Integer> intList = new ArrayList<Integer>();
		for (int i = 0; i < 5; i++) {
			intList.add(i);
		}
		intList.add(97);
		System.out.println(intList);
		System.out.println(intList.get(4));
	}
}
/*
Output:
[BerylliumSphere [id=0], BerylliumSphere [id=1], BerylliumSphere [id=2], BerylliumSphere [id=3], BerylliumSphere [id=4], null, null, null, null, null]
BerylliumSphere [id=4]
[BerylliumSphere [id=5], BerylliumSphere [id=6], BerylliumSphere [id=7], BerylliumSphere [id=8], BerylliumSphere [id=9]]
BerylliumSphere [id=9]
[1, 2, 3, 4, 5]
5
[0, 1, 2, 3, 4, 97]
4
**/

 

 16.2 数组是第一级对象

只读lengh是数组对象唯一可以访问的字段或方法,“[]”是访问数组的唯一方式。

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

 

public class ArrayOptions {
	public static void main(String[] args) {
		BerylliumSphere[] b = new BerylliumSphere[5];
		System.out.println(Arrays.toString(b));
		System.out.println(b.length);
	}
}
/*
Output:
[null, null, null, null, null]
5
**/

 数组b初始化为BerylliumSphere数组,但仍然可以通过length访问数组的大小,length只表示数组能够容纳多个元素,而不是实际保存元素的个数,这种小缺点使得无法知道数组b中确切的有多少个元素。

对象数组初始化时,其中所有的引用被初始化为null,所以检查其中的引用是否为null,就可以知道数组某个位置是否有对象。

 

int[] e;
//The local variable e may not have been initialized
System.out.println(e.length);

 数组也是对象,为初始化的null对象不访问其对象或属性,编译器就会有错误。

 

16.3 返回一个数组

public class IceCream {
	private static Random random = new Random(47);
	private static final String[] FLAVORS = new String[]{"A","B","C","D","E","F","G","H","I","J","K"};
	
	public static String[] flavorSet(int n){
		if(n>FLAVORS.length)
			throw new IllegalArgumentException("Set too big");
		String[] result = new String[n];
		boolean[] picked = new boolean[FLAVORS.length];//判断是否重复
		for (int i = 0; i < n; i++) {
			int index ;
			do {
				index = random.nextInt(FLAVORS.length);
			} while (picked[index]);//false:不重复的 true:重复的,会再次的循环
				result[i] = FLAVORS[index];
				picked[index] = true;
		}
		return result;
	}
	public static void main(String[] args) {
		System.out.println(Arrays.toString(flavorSet(3)));
	}
}

  16.4 多维数组

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

 16.5 数组与泛型

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

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

public class ParameterizedArrayType {
	public static void main(String[] args) {
		Integer[] arr = {1,2,3};
		Integer[] a = new ClassParameter<Integer>().f(arr);
		Integer[] b = MethodParameter.f(arr);
		System.out.println(Arrays.toString(a));
		System.out.println(Arrays.toString(b));
	}
}

这种方式虽可以是数组具有泛型特性,但泛型容器总是更好的选择。

 

public class ArrayOfGenericType<T> {
	T[] array;
	public ArrayOfGenericType(int size){
		//array = new T[size];//Cannot create a generic array of T
		array = (T[]) new Object[size];//Type safety: Unchecked cast from Object[] to T[]
	}
}

 泛型在类或方法上很有效,但在类或方法内部擦除泛型会带来有问题。

 16.6 创建测试数据

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

public class FillingArrays {
	public static final Integer SIZE = 6;
	public static void main(String[] args) {
		int[] a1 = new int[SIZE];
		Arrays.fill(a1, 1);
		System.out.println(Arrays.toString(a1));
		
		String[] a2 = new String[SIZE];
		Arrays.fill(a2, "a");
		System.out.println(Arrays.toString(a2));
		
		String[] a3 = new String[SIZE];
		Arrays.fill(a3, 1,3,"c");
		System.out.println(Arrays.toString(a3));
	}
}

 P443 16.6.2

 

16.7 Arrays实用功能

数组的复制

public class CopyingArrays {
	public static void main(String[] args) {
		int[] i = new int[7];
		int[] j = new int[10];
		Arrays.fill(i, 47);
		Arrays.fill(j, 99);
		System.out.println("i = "+Arrays.toString(i));
		System.out.println("j = "+Arrays.toString(j));
		System.arraycopy(i, 0, j, 0, i.length);
		System.out.println("j = "+Arrays.toString(j));
		
		Integer[] x = new Integer[7];
		Integer[] y = new Integer[10];
		Arrays.fill(x, 47);
		Arrays.fill(y, 99);
		System.out.println("x = "+Arrays.toString(x));
		System.out.println("y = "+Arrays.toString(y ));
		System.arraycopy(x, 0, y, 0, x.length);
		System.out.println("y = "+Arrays.toString(y));
		
		System.arraycopy(i, 0, y, 0, i.length);// java.lang.ArrayStoreException
	}
}
/*
Output:
i = [47, 47, 47, 47, 47, 47, 47]
j = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
j = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99]
x = [47, 47, 47, 47, 47, 47, 47]
y = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
y = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99]
Exception in thread "main" java.lang.ArrayStoreException
	at java.lang.System.arraycopy(Native Method)
	at rock.lee.c16.CopyingArrays.main(CopyingArrays.java:25)
**/

 复制对象数组,只是复制了对象的引用,而不是对象本身的拷贝,被称作“浅复制”。System.arraycopy()不会自动装箱和自动拆箱,所以两个数组成copy时必须具有相同类型,最后把int类型copy到Integer类型是不可以的。

 

数组的比较

public class ComparingArrays {
	public static void main(String[] args) {
		int[] a1 = new int[10];
		int[] a2 = new int[10];
		Arrays.fill(a1, 2);
		Arrays.fill(a2, 2);
		System.out.println(Arrays.equals(a1, a2));//true
		a2[2]= 1;
		System.out.println(Arrays.equals(a1, a2));//false
		
		String[] s1 = new String[2];
		String[] s2 = new String[]{"a","a"};
		Arrays.fill(s1, "a");
		System.out.println(Arrays.equals(s1, s2));//true
	}
}

 数组相等的条件:1、元素个数相等 2、对应位置的元素相等

通过对每一元素使用equals()作为比较判断,基本类型是通过其包装类的equals(),如Integer.equals()。

 

数组元素的比较

 

 

 

数组的排序

 

 

在以排序的数组中查找

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(第十六章 数组)