1.数组的特点<?xml:namespace prefix = o />
1)在Java中,无论使用数组或容器,都有边界检查。如果越界操作就会得到一个RuntimeException异常。
2)在Java中,数组是一种效率最高的存储和随机访问对象引用序列的方法,它的缺点是数组对象的大小被固定。
3)对象数组和基本类型数组在使用上几乎是相同的;唯一的区别是对象数组保存的是引用,基本类型数组保存基本类型的值。
4)在Java中声明数组时,无论何种方式定义数组,都不能指定其长度。
2.数组声明
1)数组在声明时,不能分配空间。只有定义完后,可以给数组分配空间。
int num[3];//error
int num[];//ok
num=new int[3];
|
或
int num[]=new int[3];
|
注意
int [] num=new int[]{1,2,3}; //ok
int [] num=new int[3]{1,2,3}; //error;
|
2)可以这样定义二维数组。
Int [][]num=new int[3][5]
//or
int [][] num;
num=new int[3][];
num[0]=new int[5];
num[1]=new int[3];
num[2]=new int[2];
|
3)二维数组赋初值。
int [][] num=new int[][]{1,2,3,4,5,5}; //error
int [][] num=new int[][]{{1,2,3},{4,5,5}}; //ok
int [][] num=new int[2][]{{1,2,3},{4,5,5}}; //error
int [][] num={{1,2,3},{4,5,6}}; //ok
|
3.数组初始化
对象数组在创建之初会自动初始化成null,由原始数据类型构成的数组会自动初始化成零(针对数值类型),(Char)0 (针对字符类型)或者false (针对布尔类型)。
4.数组引用的问题
int[] a1 = { 1, 2, 3, 4, 5 };
int[] a2;
a2 = a1;//这里只是复制了一个引用
看以下代码:
public class TestArrays {
public static void main(String[] args) {
int[] a1 = { 1, 2, 3, 4, 5 };
for (int i = 0; i < a1.length; i++)
System.out.println("a1[" + i + "] = " + a1[i]);
int[] a2;
a2 = a1;
for (int i = 0; i < a2.length; i++)
a2[i]++;
System.out.println("-----after change a2------");
for (int i = 0; i < a1.length; i++)
System.out.println("a1[" + i + "] = " + a1[i]);
System.out.println("-----after change a2[0]------");
a2[0] = 333;
System.out.println("a2[0]=" + a2[0]);
System.out.println("a1[0]=" + a1[0]);
System.out.println("----- a2------");
for (int i = 0; i < a2.length; i++)
System.out.println("a2[" + i + "] = " + a2[i]);
}
}
|
结果:
a1[0] = 1
a1[1] = 2
a1[2] = 3
a1[3] = 4
a1[4] = 5
-----after change a2------
a1[0] = 2
a1[1] = 3
a1[2] = 4
a1[3] = 5
a1[4] = 6
-----after change a2[0]------
a2[0]=333
a1[0]=333
----- a2------
a2[0] = 333
a2[1] = 3
a2[2] = 4
a2[3] = 5
a2[4] = 6
数组a1和a2始终在操作同一个对象。
5.数组的相关操作
1)在Java中,所有的数组都有一个缺省的属性length,用于获取数组中元素的个数。
2)数组的复制:System.arraycopy(src,s_index,dest,d_index,x)。意思是复制src数组中从下标s_index开始的x个元素到目标数组dest,从目标数组的下标d_index所对应的位置开始存储。
public class TestArrayCopy {
public static void main(String[] args) {
int a[]=new int[]{1,2,3,4,5};
int b[]=new int[]{9,8,7,6,5,4,3};
System.arraycopy(a, 0, b, 0, 3);
for(int i=0;i<a.length;i++)
System.out.print(a[i]);
System.out.println();
for(int i=0;i<b.length;i++)
System.out.print(b[i]);
}
}
|
结果:
12345
1236543
如果复制对象数组,那么只是复制了对象的引用,而不是对象本身。因此是浅复制。System.arraycopy()不会执行自动包装与自动拆包,两个数组必须具有相同的确切类型。
3)将一个原始数组转换为等价的对象类型数组:Array.get()。
另一个有用的技术是将一个原始数组转换为等价的对象类型数组。每个对应元素使用它们的封装器类,例如在封装数组中,37成为Integer(37)。
import java.lang.reflect.Array;
public class ArrayConv {
// if input is a single-dimension primitive array,
// return a new array consisting of wrapped elements,
// else just return input argument
public static Object toArray(Object vec) {
// if null, return
if (vec == null) {
return vec;
}
// if not an array or elements not primitive, return
Class cls = vec.getClass();
if (!cls.isArray()) {
return vec;
}
if (!cls.getComponentType().isPrimitive()) {
return vec;
}
// get array length and create Object output array
int length = Array.getLength(vec);
Object newvec[] = new Object[length];
// wrap and copy elements
for (int i = 0; i < length; i++) {
newvec[i] = Array.get(vec, i);
}
return newvec;
}
public static void main(String args[]) {
// create a primitive array
int vec[] = new int[] { 1, 2, 3 }; // wrap it
Object wrappedvec[] = (Object[]) toArray(vec);
// display result
for (int i = 0; i < wrappedvec.length; i++) {
System.out.println(wrappedvec[i]);
}
}
}
|
方法"toArray"的参数是一个Object对象(数组可以被赋值给一个Object引用)。如果参数是null或者代表的不是原始类型数组那么这个方法简单的返回参数值。java.lang.Class工具类用于判断参数是否是一个数组并获取数组的底层元素的类型。
一旦做完这些检查,使用java.lang.reflect.Array工具类的反射工具方法就可以获取原始数组的长度并获得数组的单个元素。Array.get获得的每个元素被返回到封装器类中,例如Integer或者Double。
4)填充数组:Arrays.fill()。
①fill(array,val):使用值val填充整个数组array;
②fill(array, fromIndex,toIndex,val): 使用值val填充部分数组array;
- fromIndex - 要使用指定值填充的第一个元素的索引(包括);
- toIndex - 要使用指定值填充的最后一个元素的索引(不包括);
- 如果 fromIndex > toIndex, 抛出IllegalArgumentException ;
- 如果 fromIndex < 0 或 toIndex > a.length,抛出ArrayIndexOutOfBoundsException;
- 如果 fromIndex = toIndex,则什么都不做。
import java.util.Arrays;
class Bee{}
public class FillingArrays {
public static void main(String[] args){
int[] ints=new int[3];
Bee[] bees=new Bee[3];
Arrays.fill(ints,1);
Arrays.fill(bees, 1,2,new Bee());
for(int i:ints)
System.out.print(i+",");
System.out.println();
for(Bee bee:bees)
System.out.print(bee+",");
}
}
|
结果:
1,1,1,
null,Bee@a90653,null,
5)数组比较:Arrays.equals()/Arrays.deepEquals()。
Arrays类提供了重载后的equals()方法。数组相等的条件是元素个数相等,并且对应位置的元素内容也相等。deepEquals()方法用于多维数组。
import java.util.Arrays;
public class ComparingArrays {
public static void main(String[] args) {
int int1[] = new int[] { 1, 2, 3 };
int int2[] = new int[] { 1, 2, 3 };
System.out.println(Arrays.equals(int1, int2));
String[] str1 = new String[] { "t", "t", "t" };
String[] str2 = new String[] { new String("t"), new String("t"),
new String("t") };
System.out.println(Arrays.equals(str1, str2));
}
}
|
结果:
true
true
由str1与str2的比较可以发现,比较的是内容而不是引用。
6)数组的字符串表示:Arrays.toString()/Arrays.deepToString()。
其中,deepToString()方法用于多维数组。
import java.util.Arrays;
public class ThreeDWithNew {
public static void main(String[] args){
int[][][] a=new int[2][2][4];
System.out.println(Arrays.deepToString(a));
}
}
|
结果:
[[[0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0]]]
7)数组的排序:Arrays.sort()。
import java.util.Arrays;
public class ArrSort {
public static void main(String[] args) {
int a[] = new int[] { 1, 2, 4, 8, 3 };
Arrays.sort(a);// 对数组排序
for (int i : a)
System.out.print(i);
}
}
|
结果:
12348
8)在已排序的数组中查找某个元素:Arrays.binarySearch()。
你可以在排完序的数组上进行二分法查找。
public class ArrBin {
public static void main(String[] args) {
int vec[] = { -5, 19, 23, 37, 47, 56 };
int slot = Arrays.binarySearch(vec, 35);
slot = -(slot + 1);
System.out.println("insertion point = " + slot);
}
}
|
结果:
insertion point = 3
这个程序有个微妙的概念,如果二分法查找失败它将返回:
-(insertion point) - 1
这个演示程序以参数35调用查找方法,而那个参数在数组中不存在,方法返回值-4,如果这个值加1再取其负数就得到3,这就是35应该被插入到数组中的位置,换言之,值-5, 19和23在数组中占据的位置是0,1和2。因此值35应该在索引3的位置,而37, 47以及56顺延。搜索方法并不进行实际的插入操作而只是指出应该在何处插入。
9)在数组上使用集合特性,这假设你已经有一个对象数组:Arrays.asList。
最终的范例基于前面的那个并向你展示如何在数组上使用集合特性。这假设你已经有一个对象数组。
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Array2List {
public static void main(String args[]) {
Object vec[] = { new Integer(37), new Integer(47) };
List<Object> lst = Arrays.asList(vec);
lst.set(1, new Integer(57));
for (int i = 0; i < vec.length; i++) {
System.out.println(vec[i]);
}
Iterator it=lst.iterator();
while(it.hasNext())
System.out.println(it.next());
}
}
|
在这个程序中,vec是一个对象数组,包含Integer(37) 和Integer(47),然后Arrays.asList被调用。它返回一个集合(List接口类型),使用数组作为集合的后台存储。换言之, ArrayList这样的集合类型在它内部有某种存储类型去存储集合元素。在这个例子中,使用的存储类型是作为参数传。
6.关于数组的排序操作
1)对象数组排序,必须实现Comparable接口。
import java.util.Arrays;
class Student implements Comparable {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
// 重写toString()方法,以便main:System.out.println(ss[i]);
public String toString() {
return "number=" + num + "," + "name=" + name;
}
public int compareTo(Object o) {
Student s = (Student) o;
return num > s.num ? 1 : (num == s.num ? 0 : -1);
}
}
public class TestArrayObjCopy {
public static void main(String[] args) {
Student[] ss = new Student[] { new Student(1, "zhangsan"),
new Student(2, "lisi"), new Student(3, "wangwu") };
Arrays.sort(ss);
for (int i = 0; i < ss.length; i++) {
System.out.println(ss[i]);
}
}
}
|
结果:
number=1,name=zhangsan
number=2,name=lisi
number=3,name=wangwu
2)以num为第一关键字,name为第二关键字排序
import java.util.Arrays;
class Student implements Comparable {
int num;
String name;
Student(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return "number=" + num + "," + "name=" + name;
}
public int compareTo(Object o) {
Student s = (Student) o;
int result = num > s.num ? 1 : (num == s.num ? 0 : -1);
if (0 == result) {
result = name.compareTo(s.name);
}
return result;
}
}
public class TestArrayObjCopy {
public static void main(String[] args) {
Student[] ss = new Student[] { new Student(1, "zhangsan"),
new Student(2, "lisi"), new Student(3, "wangwu"),
new Student(3, "mybole") };
Arrays.sort(ss);
for (int i = 0; i < ss.length; i++) {
System.out.println(ss[i]);
}
}
}
|
结果:
number=1,name=zhangsan
number=2,name=lisi
number=3,name=mybole
number=3,name=wangwu
7.范型数组
不能实例化具有参数类型的数组。
Fruit<Apple>[] apples=new Fruit<Apple>[]{new Apple(),new Apple(),new Apple()};//ERROR
|
但是,可以参数化数组本身的类型。
package samples;
//参数化类
class ClassParameter<T>{
public T[] get(T[] arg){
return arg;
}
}
//参数化方法
class MethodParameter{
public static <T> T[] get(T[] arg){
return arg;
}
}
class Fruit<T extends Fruit>{}
class Apple extends Fruit{}
class <?xml:namespace prefix = st1 />Orangeextends Fruit{}
class Banana extends Fruit{}
public class ParameterizedArrayType {
public static void main(String[] args) {
Apple[] apples={new Apple(),new Apple(),new Apple()};
Fruit[] genF1=new ClassParameter<Fruit>().get(apples);
Fruit[] genF2=new ClassParameter<Apple>().get(apples);
Fruit[] genF3=MethodParameter.get(apples);
for(Fruit f:genF1)
System.out.print(f+",");
System.out.println();
for(Fruit f:genF2)
System.out.print(f+",");
System.out.println();
for(Fruit f:genF3)
System.out.print(f+",");
System.out.println();
Fruit[] fruits={new Apple(),new Orange(),new Banana()};
Fruit[] genF4=new ClassParameter<Fruit>().get(fruits);
Fruit[] genF5=MethodParameter.get(fruits);
for(Fruit f:genF4)
System.out.print(f+",");
System.out.println();
for(Fruit f:genF5)
System.out.print(f+",");
}
}
|
结果:
samples.Apple@1fb8ee3,samples.Apple@61de33,samples.Apple@14318bb,
samples.Apple@1fb8ee3,samples.Apple@61de33,samples.Apple@14318bb,
samples.Apple@1fb8ee3,samples.Apple@61de33,samples.Apple@14318bb,
samples.Apple@1a758cb,samples.Orange@1b67f74,samples.Banana@69b332,
samples.Apple@1a758cb,samples.Orange@1b67f74,samples.Banana@69b332,
8.二维数组实现矩阵乘法
/**
* 两 个 矩 阵 Am¡Á n、 Bn¡Á l相 乘 得 到 Cm¡Á l,
* 每 个 元 素 Cij = aik*bkj (i=1..m,n=1..n)
*/
public class MatrixMultiply {
public static void main(String args[]) {
int i, j, k;
int a[][] = new int[2][3];
int b[][] = { { 1, 5, 2, 8 }, { 5, 9, 10, -3 }, { 2, 7, -5, -18 } };
int c[][] = new int[2][4];
for (i = 0; i < 2; i++)//行
for (j = 0; j < 3; j++)//列
a[i][j] = (i + 1) * (j + 2);
for (i = 0; i < 2; i++) {//行
for (j = 0; j < 4; j++) {//列
c[i][j] = 0;
for (k = 0; k < 3; k++)
c[i][j] += a[i][k] * b[k][j];
}
}
System.out.println("\n*** Matrix A ***");
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++)
System.out.print(a[i][j] + " ");
System.out.println();
}
System.out.println("\n*** Matrix B ***");
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++)
System.out.print(b[i][j] + " ");
System.out.println();
}
System.out.println("\n*** Matrix C ***");
for (i = 0; i < 2; i++) {
for (j = 0; j < 4; j++)
System.out.print(c[i][j] + " ");
System.out.println();
}
}
}
|
转载于:https://blog.51cto.com/860830wlx/65627