1.由于泛型和包装机制的出现,数组目前硕果仅存的优势就是效率(以前是解决存储基本类型序列的好的选择):数组是一种效率最高的存储和随机访问对象引用序列的方式。
2.数组标识符其实就是一个引用,它指向了在堆中的一个真实的数组对象,这个数组对象保存指向其他对象的引用。
3.Arays.deepToString():它可以将多维数组转换为多个String
4.粗糙数组:数组中构成矩阵的每个向量都可以有不同的长度。
5.Integer[][]a ;
a =new Integer[3][];//一维长度定义完毕
for(int i=0;i<a.length;i++){
a[i] = new Integer[10];
//定义了二维长度。
for(int j=0;j<a[i].length;j++){
//二维数组中的每一项
a[i][j] = i*j;
}
}
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]]
Integer[][][]a ;
a =new Integer[3][][];//一维长度定义完毕
for(int i=0;i<a.length;i++){
a[i] = new Integer[2][];
for(int j=0;j<a[i].length;j++){
a[i][j] = new Integer[3];
for(int x=0;x<a[i][j].length;x++){
a[i][j][x] = j*x;
}
}
}
System.out.println(Arrays.deepToString(a));
}
[[[0, 0, 0], [0, 1, 2]], [[0, 0, 0], [0, 1, 2]], [[0, 0, 0], [0, 1, 2]]]
体会下维度,只有在最后一个维度的真正的赋值(2维就是a[i][j]赋值,a[i]代表二维数组,三维就是a[i][j][k],a[i]代表二维数组,a[i][j]代表三维数组,最后a[i][j][k]用于赋值)。
6.数组与泛型:
a.)你不能实例化”具有”泛型化的数组,但是你可以泛型化数组本身的类型:
//Illegal
new A<what>[10];(如下所示,new T[]也不行,也是因为擦除)
擦除会移除参数类型信息,而数组必须知道他们所持有信息的确切类型,以强制保证类型安全。
Class A<T>{
T[] array;
Public static<T>T[]f(T[] t,int size){return t}
如上,但是我们可以泛型化数组本身的类型。
这里应该注意的是,你不能创建泛型数组!!!:
假如在方法里是{
array = new T[size];//这里就犯错了,因为创建的时候类型被擦除,此时类型为未知,你创建不了类型未知的数组,如果创建的是Object数组,再转型,就可以了,因为Object数组可以包含除了基本类型外的所有类型。
}
}
b.)但是它允许创建泛型数组引用:
A<What>[] a;
尽管你不能创建实际的泛型数组,但是你可以创建非泛型数组,然后强制转型为泛型数组;
List<String>[] example;
List[] l = new List[10];
example = (List<String>[])l;
c.)数组是可协变类型的:
List[]l =new ArrayList[10];
Object[]object =l;
ArrayList[]b =new ArrayList[10];
List[]test =b;
如上,数组可以很自然的转换到其父类类型的数组。
7.Arrays.fill(数组,值):这个方法的作用十分有限,它只能用同一个值填充数组的各个地方。
8.关于JAVA中的math.round :不能完全等同是四舍五入,其实有规律的:参数的小数点后一位,大于五全部加,等于五正数加,小于五全不加。(这里的全是指正数和负数情况)
9.Arrays实用功能:
以下所有方法都是Arrays.xxx
a.) equals(数组a,数组b)用于比较两个数组是否相等。
(数组本身没有equals方法,但是因为Java中所有的类都继承Object,所以他调用的是Object的equals方法,这个equals方法的声明是:
public boolean equals(Object obj) {
return (this == obj);
}
所以说你做的比较是比较两个数组的内存地址,所以是false)
如果你要比较着两个数组的内容的话,可以这样写 Arrays.equals(ch,c)
Arrays.equals()比较的是内容,数组本身没有equals,但是所有类继承自Object,所以调用的是Object的equals()。比较的是内存地址
b.)deepEquals()用于多维数组;
c.)fill()在数组中的每个位置填上同一个值;
d.)sort()用于数组排序;
e.)binarySearch()用于在排序后的数组中查找元素;(数组要使用二分查找法必须先排序才可以)
f.)toString();
g.)hashCode()产生数组的散列码。
10.复制数组System.arrayCopy(源数组,源数组开始位置,目标数组,目标数组开始位置,复制长度):
需要知道的有:
用它复制数组比for循环赋值数组快的多。
也可以复制对象,但是复制对象的时候复制的是对象的引用--成为”浅复制”
这个方法不会执行自动包装和自动拆包,所以源数组和目标数组必须具有相同的确切类型。
Integer[]a =new Integer[]{new Integer(5),new Integer(2),new Integer(3),new Integer(10)};
Integer[]b =new Integer[7] ;
System.arraycopy(a, 0, b, 0,a.length);
System.out.println(Arrays.toString(b));
11.数组元素的比较:
第一种方式,如果你自定义了一个数组,你想让你的数组元素有比较的能力,即可以应用于Arrays.sort()方法中,那么你应该让你数组中的类实现Comparable接口,这会强制你实现compareTo()方法,例子如下:
public static void main(String[]args) {
A[]a = {
new A(),new A(),new A(),new A(),new A()
};
System.out.println(Arrays.deepToString(a));
System.out.println("排序后");
Arrays.sort(a);
System.out.println(Arrays.deepToString(a));
}
}
class Aimplements Comparable<A>{
Random rand =new Random();
int i =rand.nextInt(20);
@Override
public int compareTo(Ao) {
return (i < o.i ? -1 : (i==o.i? 0 : 1));
}
public String toString(){
return " "+i;
}
}
在compareTo()方法中,如果当前值小于比较值,返回负值; 如果相等,返回0;如果大于,返回正值。
如果你没用实现Comparable接口,调用sort()的时候ClassCastException运行时异常。因为sort()需要把参数的类型转换为Comparable。
问题:如果你的一个类没有实现Comparable,或者已经实现Comparable,但是你不喜欢它的排序方式,那么怎么办?
第二种方式:用系统已有的 或者 自己生成自己的Comparator。
public static <T> void sort(T[] a,Comparator<? super T> c)
请看,方法的第二个参数,是通过Comparator进行比较的。
a.)Collections.reverseOrder()方法产生一个倒序的Comparator,如下:
public static void main(String[]args) {
A[]a = {
new A(),new A(),new A(),new A(),new A()
};
System.out.println(Arrays.deepToString(a));
System.out.println("排序后");
//Arrays.sort(a);
Arrays.sort(a,Collections.reverseOrder());
System.out.println(Arrays.deepToString(a));
}
}
b.)你也可以定义自己的Comparator:
public static void main(String[]args) {
A[]a = {
new A(),new A(),new A(),new A(),new A()
};
System.out.println(Arrays.deepToString(a));
System.out.println("排序后");
//Arrays.sort(a);
//Arrays.sort(a,Collections.reverseOrder());
Arrays.sort(a,new AComparator());
System.out.println(Arrays.deepToString(a));
}
}
class A {
Randomrand =new Random();
int i =rand.nextInt(20);
//@Override
//publicint compareTo(A o) {
//return (i<o.i?-1:(i==o.i?0:1));
//}
public String toString(){
return " "+i;
}
}
class AComparatorimplements Comparator<A>{
@Override
public int compare(Ao1, Ao2) {
return (o1.i<o2.i?-1:(o1.i==o2.i?0:1));
}
}
关于字符串的排序需要注意的地方:
String排序算法根据词典编排序,大写字母放在前面输出,然后才是小写字母,如果你希望忽略大小写,可以sort(String s,String.CASE_INSENSITIVE_ORDER);
总结:只要我们要比较的对象实现了Comparable或者我们有相关的Comparator,那么我们就可以进行数组元素的比较。Java中默认对基本类型进行快速排序,对对象进行稳定归并排序。
12.在已经排序的数组中查找元素:
如果找到了目标,Arrays.binarySearch()产生的返回值等于或者大于0;
public static void main(String[]args) {
Aa3 =new A(7);
A[]a = {
new A(3),new A(5),a3,new A(10),new A(11),new A(2),new A(6)
};
System.out.println(Arrays.deepToString(a));
System.out.println("排序后");
//Arrays.sort(a);
//Arrays.sort(a,Collections.reverseOrder());
Arrays.sort(a,new AComparator());
System.out.println(Arrays.deepToString(a));
System.out.println(Arrays.binarySearch(a,a3,new AComparator()));
}
}
class A {
int i;
A(int i ){
this.i =i;
}
public String toString(){
return " "+i;
}
}
class AComparatorimplements Comparator<A>{
@Override
public int compare(Ao1, Ao2) {
return (o1.i<o2.i?-1:(o1.i==o2.i?0:1));
}
}
[ 3, 5, 7, 10, 11, 2, 6]
排序后
[ 2, 3, 5, 6, 7, 10, 11]
4
注意:如果用Comparator排序了某个对象数组,在使用binarySearch()的时候你需要提供你的Comparator。
Arrays.binarySearch(a,a3,new AComparator())
第一个参数是目标数组,第二个是目标,第三个你的比较器。
如果数组中有重复的元素,无法保证最终找到的是这点些副本中的哪一个,如果需要对没有重复元素的数组排序,可以使用TreeSet和LinkedHashSet。