20.1 一维数组

数组学习:

1.数组的特点

  • 数组是引用数据类型,所以数组对象(动态初始化使用new关键字)是存放在堆内存中的。数组的父类是Object
  • 数组实际上是一种容器,可以存储一组数据既可以存储基本数据类型,也可以存储引用数据类型数组中存储 Java对象时,存储的是实际对象的引用(在堆内存中的地址),而不是具体的对象数组不能直接存储实际对象
  • 数组一旦创建(不管是静态初始化还是动态初始化),其长度就不能再改变。
  • 数组分为:一维数组,二维数组,多维数组…
  • 数组对象自带length属性,数组名.length返回数组的长度
  • 数组中的数据类型必须保持一致,和数组的声明类型一致
  • 数组存储在一块连续的内存空间上,即数组元素的内存地址是连续的,数组是一种简单的数据结构。
  • 数组名存放了数组首元素的地址,数组使用首元素的地址作为整个数组的内存地址。因为数组的内存空间是连续的,长度确定,只需要知道首地址即可。
  • 数组有下标。从0~length-1。下标使得访问数组元素十分方便。

2.数组的优点和缺点

  • 优点

因为数组内存是一块连续的内存空间,数组元素的数据类型一致,数组有下标。使得我们访问(查找/存取)数组元素十分方便。即数组是一种随机存取的数据结构。只需要知道数组中某个元素的地址,此时访问其他元素只需进行相应的偏移即可。随机存取的时间复杂度是O(1)的。

数组中存储100个元素,或者存储100万个元素,在元素查询/检索方面,效率是相同的,
因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的。(算出一个
内存地址,直接定位的。)
  • 缺点

同样,因为数组要求数组中元素的内存是连续的。在进行数组中非末尾元素的增加与删除时,必须移动改动位置后的每一个元素,一般来说时间复杂度是O(n)。

此外,数组的内存空间是连续的,当数组对象较多时,容易造成堆空间内存碎片较多。或者对于大容量的数组,很难在内存中找到一块足够大的连续空间。

3.一维数组的声明(定义)

int[] array;
double array[];
String[] array;
Person[] array;
......

4.一维数组的初始化

  • 静态初始化
int[] arr = {1,2,3,4,5};
Object[] arr1 = {new Object(),new Object(),new Object()};
  • 动态初始化
int[] arr = new int[length];//使用new关键字创建数组对象
  • 什么时候静态初始化?什么时候动态初始化
当你创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式。
当你创建数组的时候,不确定将来数组中存储哪些数据,你可以采用动态初始化的方式,预先分配内存空间。

5.传递参数是数组怎么传?

  • 直接传递数组
package com.study.array;

public class ArrayTest01 {
    //方法的参数是数组
    public static void main(String[] args) {
        String[] s = {"aaa","bbb","ccc"};
        printArray(s);
    }
    

    public static void printArray(String[] str){//打印
        for (String s :
                str) {
            System.out.println(s);
        }
    }
}
/*
aaa
bbb
ccc
*/
  • 创建对象后直接初始化并传递
package com.study.array;

public class ArrayTest01 {
    //方法的参数是数组
    public static void main(String[] args) {
       
        //静态初始化并传递
        printArray(new String[]{"ddd","eee","fff"});
    }


    public static void printArray(String[] str){//打印
        for (String s :
                str) {
            System.out.println(s);
        }
    }
}
/*
ddd
eee
fff
*/

6. main方法中的String[] args有什么用?

分析:谁负责调用main方法?

JVM 负责调用main方法,并且JVM调用main方法的时候,会自动传一个String数组过来。

测试一下String[] args这个数组:

package com.study.array;

public class ArrayTest02 {
    public static void main(String[] args) {
        System.out.println(args.length);
    }
}
//0

输出的args数组的长度是0,所以args不是null。否则会有空指针异常。

args不是null就表示args这个引用实际已经指向了某一对象,即已经创建了一个String[]的对象。

这个数组什么时候里面会有值呢?
其实这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动会被转换为“String[] args”
例如这样运行程序:java ArrayTest05 abc def xyz
那么这个时候JVM会自动将“abc def xyz”通过空格的方式进行分离,分离完成之后,自动放到“String[] args”数组当中。
所以main方法上面的String[] args数组主要是用来接收用户输入参数的。
把abc def xyz 转换成字符串数组:{"abc","def","xyz"}
package com.study.array;
//在IDEA中设置带参数的运行
//java ArrayTest02 abc def sss rrr
public class ArrayTest02 {
    public static void main(String[] args) {
        System.out.println(args.length);
        for (String s :
                args) {
            System.out.println(s);
        }
    }
}
/*
4
abc
def
sss
rrr
*/

使用String[] args数组写一个案例

package com.study.array;
//假设我们要写一个需要用户名和密码的系统如下
//利用String[] args数组
public class ArrayTest03 {
    public static void main(String[] args) {
        // // 用户名和密码输入到String[] args数组当中。
        if(args.length != 2){
            System.out.println("请输入账号密码");
            return;
        }
        // 程序执行到此处说明用户确实提供了用户名和密码。
        // 接下来你应该判断用户名和密码是否正确。
        //判断两个字符串是否相等,需要使用equals方法。
        //if(username.equals("admin") && password.equals("123")){
        // 这样编写是不是可以避免空指针异常。
        // 采用以下编码风格,即使username和password都是null,也不会出现空指针异常。(这是老程序员给的一条编程经验。)
        if("admin".equals(args[0]) && "123".equals(args[1])){
            System.out.println("欢迎使用本系统");
        }else{
            System.out.println("账号密码错误");
        }
    }
}

7.数组存储引用数据类型拓展

当数组存储引用类型数据时,存储的并不是实际的Java对象,实际上存储的是Java对象的“内存地址”,是指向对象的引用!

在这里插入图片描述

  • 数组中的元素数据类型必须一致。但是,当数组中元素为引用类型时,数组中的元素可以是父子类关系:
package com.study.array;

public class ArrayTest04 {
    public static void main(String[] args) {
        Animal[] animals ={new Animal(),new Animal()};
        //print(animals);
        for (int i = 0; i < animals.length; i++) {
            animals[i].move();
        }
        System.out.println("===============================");
        Animal[] ans = new Animal[2];
        //数组中的引用数据类型可以存储数组类型的子类对象(多态)
        ans[0] = new Cat();
        ans[1] = new Dog();
        for (int i = 0; i < ans.length; i++) {
            ans[i].move();
        }
        System.out.println("===============================");
        //当数组中元素是子类对象时,调用子类独有的方法需要进行向下转型。向下转型需要进行判断
        Animal[] animals1 = {new Cat(),new Dog()};
        for (int i = 0; i < animals1.length; i++) {
            if (animals1[i] instanceof Cat){
                ((Cat) animals1[i]).catchMouse();
            }else if (animals1[i] instanceof Dog){
                ((Dog) animals1[i]).catchMouse();
            }
        }
    }
    public static void print(Object[] obj){
        for (Object o : obj) {
            System.out.println(o);
        }
    }
}
class Animal{
    public void move(){
        System.out.println("动物在移动!");
    }
}
class Cat extends Animal{
    @Override
    public void move() {
        System.out.println("猫猫冲击!");
    }
    public void catchMouse(){
        System.out.println("猫抓老鼠!");
    }
}
class Dog extends Animal{
    @Override
    public void move() {
        System.out.println("汪汪队立大功!");
    }
    public void catchMouse(){
        System.out.println("狗拿耗子!");
    }
}

8.数组扩容与数组拷贝

在java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
*      数组满了,需要扩容。
*      java中对数组的扩容是:
*          先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。然后小数组被垃圾回收器回收。
*
* 结论:数组扩容效率较低。因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。
* 可以在创建数组对象的时候预估计一下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。
  • 数组拷贝方法(5个参数)
public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, 
                                        int destPos,
                                        int length);
 arraycopy(拷贝源,拷贝起始位置,目标源,目标起始位置,拷贝长度)
package com.study.array;

public class ArrayTest05 {
    public static void main(String[] args) {
        int[] src = {1,2,3,4,5};
        int[] dest = new int[10];
        System.arraycopy(src,0,dest,0,src.length);
        for (int i = 0; i < dest.length; i++) {
            System.out.print(dest[i]+"\t");
        }
        System.out.println();
        System.out.println("=========================");
        String[] strs = {"sss","aaa","bbb"};
        String[] ss = new String[6];
        System.arraycopy(strs,0,ss,0,strs.length);
        print(ss);
        System.out.println("=========================");
        Object[] objs = {new Object(),new Object(),new Object()};
        Object[] objects = new Object[6];
        System.arraycopy(objs,0,objects,1,objs.length);
        print(objects);
    }
    //遍历打印引用数据类型的数组
    public static void print(Object[] obj){
        for (Object o : obj) {
            System.out.println(o);
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值