Thking in java(第四版)-查缺补漏(第16章)

背景

继续查缺补漏,充电

1.数组的特点

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

(2)数组对象的大小固定,并且在其生命周期不可改变。

(3)可以通过编译器检查,防止插入错误类型和抽取不当类型。

(4)数组标识符其实只是一个引用,指向在堆中创建的一个真实对象,这个(数组)对象

用来保存指向其他对象的引用。

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

2.多维数组

语法如下所示:

int[][] a={ {1,2,3}, {4,5,6}, };

int[][][] a=new int[2][2][4];

Random rand=new Random(47);
int[][][] a=new int[rand.nextInt(7)][][];
for(int i=0;i<a.length;i++){
	a[i]=new int[rand.nextInt(5)][];
	for(int j=0;j<a[i].length;j++)
		a[i][j]=new int[rand.nextInt(5)];
}

3.Arrays

(1)Arrays.deepToString()方法:可以将多维数组转换为多个String。

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

boolean[] a1=new boolean[size];
Arrays.fill(a1,true);

 (3)Arrays.asList()方法:接收任意的序列或数组作为参数,将其转变为List容器。

4.复制数组

System.arraycopy() 不会执行自动包装和自动拆包。

5.数组比较

Arrays类提供了重载后的equals方法,用来比较整个数组。

6.数组元素的比较

(1)实现Comparable接口,重写compareTo()方法。

使用Arrays.sort()方法进行比较

package arrays;
import java.util.*;
import tools.*;
import static tools.Print.*;
public class CompType implements Comparable<CompType> {
	int i;
	int j;
	private static int count=1;
	public CompType(int n1,int n2){
		i=n1;
		j=n2;
	}
	public String toString(){
		String result="[i= "+i+",j="+j+"]";
		if(count++%3==0)
			result +="\n";
		return result;
	}
	public int compareTo(CompType rv){
		return (i<rv.i?-1:(i==rv.i?0:1));
	}
	private static Random r=new Random(47);
	public static Generator<CompType> generator(){
		return new Generator<CompType>(){
			public CompType next(){
				return new CompType(r.nextInt(100),r.nextInt(100));
			}
		};
	}
	public static void main(String[] args){
		CompType[] a=new CompType[10];
		Generator<CompType> n= CompType.generator();
		for(int i=0,j=a.length;i<j;i++)
			a[i]=n.next();
		print(Arrays.toString(a));
		Arrays.sort(a);
		print(Arrays.toString(a));
	}
}

使用Arrays.sort(a,Collections.reverseeOrder()) 来反转自然的排序顺序。Collection类的reverseOrder()方法

会产生一个Comparator。 

(2)创建实现Comparator接口的单独的类。接口有compare()和equals()方法。一般不实现equals(),除非有特

殊的性能需求。

package arrays;
import java.util.*;

import tools.*;
import static tools.Print.*;
class CompTypeComparator implements Comparator<CompType>{
	public int compare(CompType o1,CompType o2){
		return (o1.j<o2.j?-1:(o1.j==o2.j)?0:1);
	}
}
public class ComparatorTest {
	public static void main(String[] args){
		CompType[] a=new CompType[10];
		Generator<CompType> n= CompType.generator();
		for(int i=0,j=a.length;i<j;i++)
			a[i]=n.next();
		Arrays.sort(a,new CompTypeComparator());
		print(Arrays.toString(a));
	}
}

 7.数组排序

使用内置的排序方法,可以对任意的基本类型数组排序;对任意的对象数组排序,

只要该对象实现了Comparable接口或具有相关联的Comparator。

想忽略大小写字母将单词都放在一起排序,可以使用String.CASE_INSENSITIVE_ORDER

Arrays.sort(sa,String.CASE_INSENSITIVE_ORDER)

 针对基本类型采用“快速排序”,针对对象用“稳定归并排序”。

8.在已排序的数组中查找

如果数组已经排序,用Arrays.binarySearch()。

如果使用了Comparator排序了某个对象数组(基本类型数组无法使用Comparator进行排序),

在使用binarySearch()时必须提供同样的Comparator。

9.数据生成器

下面采用了策略设计模式,每个不同的Generator都表示一个不同的策略

package tools;

public 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 Character 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 Character();
		public String(){}
		public String(int length){	this.length=length;}
		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 Float implements Generator<java.lang.Float>{
		private float  value=0;
		public java.lang.Float next(){
			float result=value;
			value+=1.0;
			return result;
		}
	}
	public static class Double implements Generator<java.lang.Double>{
		private double value=0.0;
		public java.lang.Double next(){
			double result=value;
			value+=1.0;
			return result;
		}
	}
}

可以利用反射来测试Generator的任何集合,例如:


import tools.*;
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.printf(g.next()+" ");
				System.out.println();
			}catch(Exception e){
				throw new RuntimeException(e);
			}
		}
	}
	public static void main(String[] args){
		test(CountingGenerator.class);
	}
}

下面试转换器,可以接受任意包装器对象数组,然后转化成相应的基本类型数组:

package tools;

public class ConvertTo {
	public static boolean[] primitive(Boolean[] in){
		boolean[] result=new boolean[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=in[i];
		return result;
	}
	public static char[] primitive(Character[] in){
		char[] result=new char[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=in[i];
		return result;
	}
	public static byte[] primitive(Byte[] in){
		byte[] result=new byte[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=in[i];
		return result;
	}
	public static short[] primitive(Short[] in){
		short[] result=new short[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=in[i];
		return result;
	}
	public static int[] primitive(Integer[] in){
		int[] result=new int[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=in[i];
		return result;
	}
	public static long[] primitive(Long[] in){
		long[] result=new long[in.length];
		for(int i=0;i<in.length;i++)
			result[i]=in[i];
		return result;
	}
	 public static float[] primitive(Float[] in){
		 float[] result=new float[in.length];
		 for(int i=0;i<in.length;i++)
			 result[i]=in[i];
		 return result;
	 }
	 public static double[] primitive(Double[] in){
		 double[] result=new double[in.length];
		 for(int i=0;i<in.length;i++)
			 result[i]=in[i];
		 return result;
	 }
}

总结

优选容器而不是数组,只有在已证明性能成为问题时,才应该将程序重构为使用数组。

猜你喜欢

转载自blog.csdn.net/a614528195/article/details/82113744
今日推荐