Java-一维数组总结

Array综述

  1. java 语言中的数组是一种引用数据类型。不属于基本数据类型,数组的父类是 object。
  2. 数组实际上是一个容器,可以同时容纳多个元素(数组是一个数据的集合)
    数组: 字面意思是"一组数据"
  3. 数组当中可以存储"基本数据类型"的数据,也可以存储"引用数据类型" 的数据
  4. 数组因为是引用类型,所以数组对象是堆内存当中(数组是存储在堆内存当中的)
  5. 数组当中如果存储的是"Java对象" 的话,实际上存储的是对象的"引用(内存地址)"
  6. 数组一旦创建,在java 中规定,长度不可变(数组长度不可以变)
  7. 数组的分类: 一维数组,二维数组,多维数组。。。。(一维数组较多, 二维数组偶尔使用)
  8. 所有的数组对象都有length属性(java自带的)用来获取数组中元素的个数
  9. java中的数组要求数组中元素的类型统一。
    比如: int 类型数组只能存储int 类型,Person 类型数组只能存储Person 类型。
    例如: 超市购物,购物袋中只能装苹果。不能同时装苹果和橘子(数组中存储的元素类型统一)
  10. 数组在内存方法存储的时候,数组中元素的内存地址(存储的每一个元素都是有规则的挨着排列的)是连续的。
    内存地址连续这是数组存储元素的特点,数据实际上是一种简单的数据结构。
  11. 所有的数组都是拿"第一个小方框的内存地址"作为整个数组对象的内存地址。(数组中首元素的内存地址作为整个数组对象)
  12. 数据中每个元素都是有下标的, 下标从0开始,以1递增。最后一个元素的下标是 length -1下标非常重要,因为我们对数组中元素进行"存取",都需要通过下标来进行的。

Java-一维数组总结_第1张图片

数组的优缺点

优点

查询/查找/检索 某个下标上的元素时效率极高,可以说是查询效率最高的一个数据结构。

为什么检索效率高?

  • 每一个元素的内存地址在空间存储上是连续的。
  • 每一个元素类型相同。所以占用的空间大小一样。
  • 知道第一个元素的内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率最高。

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

缺点

  • 由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素时(非末尾元素),效率较低,因为随机增删元素会涉及到最后元素统一向前或者向后位移操作。

  • 数组不能存储大数据量,为什么? 因为很难在内存空间上找到一块特别大的连续内存空间。

注意 对于数组中最后一个元素的增删,是没有效率影响的。

一维数组 声明/定义

语法格式:
 int[] array1;
 double[] array2;
 boolean[] array3;

一维数组初始化

静态初始化

 静态初始化语法格式:
    int[] array = {100,232,343};

动态初始化

动态初始化语法格式:
 int[] array = new int[5]; // 这里的5 表示数组的元素个数。
                         // 初始化一个5个长度的int类型数组,每个元素会赋值默认0
String[] names  = new String[5];// 初始化一个6个长度的String类型数组,每个元素默认null

什么时候采用静态初始化方式?什么时候使用动态初始化方式?
当你创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式。
当你创建数组的时候,不确定将来数组中存储哪些数据,你可以采用动态初始化的方式,预先分配内存地址

一维数组深入

对于数组来说,实际上只能存储java对象的"内存地址" 。 数组中存储的每个元素是"引用"

扩容

在java 开发中,数组长度一旦确定不可变。那么数组满了怎么办?

扩容方式

先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大容量的数组中

结论

数组扩容 效率较低,因为涉及到拷贝的问题,所以在以后的开发中请注意: 尽可能少的进行数组的拷贝。 可以在创建数组对象的时候预估以下多长合适,最好预估准确,这样可以减少数组扩容次数,提高效率

数组拷贝

Java-一维数组总结_第2张图片

代码演练

public class ArrayTest01 {
    public static void main(String[] args) {
        //声明一个int 类型的数组, 使用静态初始化的方式
        //java风格
        int[] a1 = {1,100,10,20,55,689};
        //c++风格
//        int a1[] = {1,100,10,20,55,689};

        //所有的数组对象都有length属性
        System.out.println(a1.length);


        //数组中每个元素都有下标
        //通过下标对数组的元素进行存/取


        //取(读)
        System.out.println("第一个元素="+a1[0]);
        System.out.println("最有一个元素="+a1[a1.length-1]);

        //存(改)
        //把第一个元素改为 123
        a1[0]=123;
        //把最后一个元素改为 0
        a1[a1.length-1]=0;

        System.out.println("第一个元素="+a1[0]);
        System.out.println("最有一个元素="+a1[a1.length-1]);

        //一维数组遍历
        for(int i=0; i<=a1.length-1;i++){
            System.out.println(a1[i]);
        }
        //数组越界异常 java.lang.ArrayIndexOutOfBoundsException
//        System.out.println(a1[6]);//

     // 动态初始化
        Object[]  ob = new Object[3];

        for(int i=0; i<=ob.length-1;i++) {
            System.out.println(ob[i]);
        }

        //存储Object,采用静态初始化

        Object  ob1 = new Object();
        Object  ob2 = new Object();
        Object  ob3 = new Object();
        Object[]  obs = {ob1,ob2,ob3};
        System.out.println(obs);
        for(int i=0; i<=obs.length-1;i++) {
            System.out.println(obs[i]);
        }


        System.out.println("=============");
        printArray(a1);
        System.out.println("*************");
        printArray(new String[5]);

        System.out.println("++++++++++++++");
        printArray(new int[]{23,334,56});

        System.out.println(args.length);

        System.out.println("ttttttttttt");
        // 创建一个Animal类型的数组,里面存储了cat 和Bird

        Animal[] animals = {new Cat(),new Bird()};//该数组中存储了两个对象的内存地址

        for (int i = 0; i<animals.length;i++){
            //从animals中取出来的可能是Cat,也可能是Bird 不过肯定是一个Animal
            // 如果调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用即可

//            Animal an = animals[i];
//                  an.move();

            animals[i].move();
            if (animals[i] instanceof Bird){
                Bird bird = (Bird)animals[i];
                bird.sing();

            }

        //数组拷贝
            //System.arraycopy(5个参数)
            //拷贝源(从这个数组中拷贝)
            int[] aa1 = {1,100,10,20,55,689};

            // 拷贝目标 (拷贝到这个目标数组上)
            int[] dest = new int[10];//动态初始化一个长度为10的数组

            //调用System.arraycopy() 拷贝aa1 中的 第2,3 元素到 dest的3,4位置上

            System.arraycopy(aa1,1,dest,2,2);

            //循环输出
            for(int t=0; t<dest.length;t++) {
                 System.out.println(dest[t]);
            }
            System.out.println("————————————————————");
            //数组中如果存储的元素是引用,可以拷贝吗? 当然可以

            Object[] obj = {new Object(),new Object(),new Object()};
            Object[] newObj = new Object[10];

            // 思考: 这里拷贝的时候,拷贝的是对象还是对象地址? (地址)
            //将obj数组中所有的元素全部拷贝到newObj中
            System.arraycopy(obj,0,newObj,0,obj.length);
            for(int t=0; t<newObj.length;t++) {
                System.out.println(newObj[t]);
            }
        }

    }
    public static void printArray(int[] array){

        for(int i=0; i<=array.length-1;i++) {
            System.out.println("int数组: "+array[i]);
        }

    }

    public static void printArray(String[] args){

        for(int i=0; i<=args.length-1;i++) {
            System.out.println("String 数组中的元素: "+args[i]);
        }

    }
}

class Animal{
    public void move(){
        System.out.println("move");
    }
}

class Cat extends Animal{
    public void move(){
        System.out.println("Cat");
    }

}
class Bird extends Animal{
    public void move(){
        System.out.println("Bird");
    }

    public void sing(){
        System.out.println("Bird sing");
    }
}

你可能感兴趣的:(java,数据结构)