数组
1.数组的概念
-
数组是一种引用数据类型,不是基本数据类型,父类是Object
-
数组实际上是一个容器,可以容纳多组数据
-
数组可以存储基本数据类型,也可以存储引用数据类型
-
数组长度不可变
-
数组存储的类型统一,一种类型的数组只能存放该种类型的数据
-
数组存储的数据内存地址是连续的
-
数组的优缺点:
- 优点
- 查询效率极高,直接定位,无需遍历
- 缺点
- 增加和删除元素效率极低,需要大量移动元素(增加或删除最后一个元素除外)
- 很难找到大片的连续空间
- 内存图:
2.一维数组
2.1 一维数组的初始化
int[] array1;//声明数组
int[] array2={100,200,300};//静态初始化
int[] array3=new int[5];//动态初始化,初始化一个长度为5的int类型数组,每个元素默认值为0
静态初始化:知道需要存什么数据,直接存
动态初始化:不知道需要存什么数据,先开辟空间
2.2 一维数组元素的访问
int[] a={1,3,2,3,4,7};
a[2]=100;//元素的修改
System.out.println("第一个元素是"+a[0]);
System.out.println("最后一个元素是"+a[a.length-1]);
System.out.println("数组的元素的个数是"+a.length);
2.3 一维数组元素的遍历
for(int i=0;i<a.length;i++)
System.out.println(a[i]);//正序遍历
for(int i=a.length-1;i>=0;i--)
System.out.println(a[i]);//逆序遍历
引用类型数组遍历
Object obj1=new Object();
Object obj2=new Object();
Object obj3=new Object();
Object[] obj={obj1,obj2,obj3};
for(int i=0;i<obj.length;i++)
System.out.println(obj[i]);//存放Object类型的引用,默认值为null
2.4 方法的参数是数组
int[] a={1,2,3};
print(a);//传入数组
print(new String[3]);
print(new int[]{1,2,3});
public static void print(int[] arr)
{
for(int i=0;i<arr.length;i++)
System.out.println(arr[i]);
}
2.4.1 main方法中的String数组参数
public static void main(String[] args){}
- 默认传入一个空的String数组(不是null)
- 该数组是留给用户输入使用的
- java Test01 abc def jkl在终端这样运行程序的时候,JVM会自动将abc def jkl转化为字符串,放入数组中,作为参数传入main方法,这样调用以下main方法
- 输出为:
- abc
- def
- jkl
public static void main(String[] args)
{
for(int i=0;i<args.length;i++)
System.out.println(args[i]);
}
- 小练习
-
class Register { public static void main(String[] args) { if(args.length!=2) { System.out.println("使用该系统时,请输入用户名和密码信息,例如:zhangsan 123"); return; } String username=args[0]; String password=args[1]; if("admin".equals(username)&&"123".equals(password)) //防止空指针异常(username.equals()容易发生空指针异常) System.out.println("登陆成功!!"); else System.out.println("登陆失败,用户名或验证码错误"); } }
-
2.4.2 数组的元素是引用数据类型
引例:
public class Test01 {
public static void main(String[] args) {
Animals[] animals = new Animals[5];//动态初始化一个Animals类型数组,存入5个Animals类型引用,初始化为null
animals[0] = new Animals();//数组第一个元素指向一个Animals实例对象
animals[1] = new Cat();//数组第二个元素指向一个Cat实例对象,多态,父类Animals类型引用指向子类对象
Cat c = new Cat();//创建Cat实例化对象
Bird b = new Bird();//创建Bird实例化对象
Animals[] anim = {b, c};//将b,c对象存入anim数组中
for (int i = 0; i < anim.length; i++)//循环调用数组中move方法(父类子类共有方法)
{
anim[i].move();
}
for (int i = 0; i < anim.length; i++)//循环调用数组中特有方法
{
if (anim[i] instanceof Cat)//如果指向的是Cat对象,向下转型,调用特有方法
{
Cat cc = (Cat) anim[i];
cc.CatchMouse();
}
if (anim[i] instanceof Bird)//如果指向的是Bird对象,向下转型,调用特有方法
{
Bird bb = (Bird) anim[i];
bb.sing();
}
}
}
}
class Animals
{
public void move()
{
System.out.println("Animal 正在移动。。。");
}
}
class Cat extends Animals
{
public void move()//重写父类方法
{
System.out.println("Cat 正在移动。。。");
}
public void CatchMouse()//特有方法
{
System.out.println("Cat is catching mouse。。。");
}
}
class Bird extends Animals
{
public void move()//重写父类方法
{
System.out.println("Bird 正在移动。。。");
}
public void sing()//特有方法
{
System.out.println("Bird is singing。。。");
}
}
2.5 数组的扩容
2.5.1 数组的扩容原理
- 数组扩容实际上是创建一个大数组,将原数组拷贝到大数组中
- 所以效率非常非常低
2.5.2 数组的扩容方法
- 数组拷贝方法
System.arraycopy(b,0,a,0,5);//(源数组,起始位置,拷贝到数组,起始位置,拷贝长度)
public class ArrayTest {
public static void main(String[] args){
int[] large=new int[8];//扩容的大数组
int[] small={1,2,3,4,5};//源数组
System.arraycopy(small,0,large,0,5);//数组拷贝
for (int i = 0; i < large.length; i++) {
System.out.print(large[i]+" ");//打印数组
}
}
}
- 引用类型数组的拷贝
public class ArrayTest {
public static void main(String[] args){
Object o1=new Object();
Object o2=new Object();
Object o3=new Object();//创建三个对象
Object[] newobjs=new Object[5];//新数组
Object[] objs={o1,o2,o3};//源数组
System.arraycopy(objs,0,newobjs,0,3);//数组拷贝
for (int i = 0; i < newobjs.length; i++) {
System.out.print(objs[i]);
}
}
}
- 内存图
实际上还是三个对象,并没有创建新的对象
3.二维数组
3.1 二维数组初始化
int[][] a={{0,1,2}, {3,4,5}};
int[][] b=new int[2][3];
- 二维数组本质是特殊的 一维数组
- 只是每个元素都是一个一维数组
3.1.1 二维数组的遍历和访问
- 二维数组的遍历
System.out.println(a.length);//2(因为本质是一维数组,这个二维数组里面有两个元素,分别都是一维数组)
System.out.println(a[0].length);//3
for (int i = 0; i < b.length; i++) {//外层表示一次取出二维数组中的每一个一维数组
for (int j = 0; j < b[i].length; j++) {//内层表示取出这个一维数组的每个元素
System.out.print(b[i][j]+" ");
}
}
- 二维数组元素的访问
System.out.println(a[0][0]);
//分步
int[] b=a[0];//a[0]是第一个一维数组元素的首地址
System.out.println(b[0]);
3.2.2 二维数组作为方法的参数
public class ArrayTest {
public static void main(String[] args) {
int[][] a={{1,2,3},{4,5,6}};
print(a);//将二维数组传入方法中
}
public static void print(int[][] a){
for (int i = 0; i < a.length; i++) {
for (int j = 0; j <a[i].length; j++) {
System.out.print(a[i][j]);
}
}
}
}
4. 数组常用方法
4.1 数组拷贝
int[] copy=nums.clone();//拷贝数组