精华内容
下载资源
问答
  • 问题描述 给出一个包含n个整数的数列,问整数a在数列中的第一次出现是第几个。 输入格式 第一行包含一个整数n。 第二行包含n个非负整数,为给定的数列,数列中的每个数都不大于10000。 ...第三行包含一个整数a,为待...
  • Java——数组

    2021-01-24 10:00:45
    Java数组1. 数组概述2. 一维数组(1). 创建一维数组(2). 初始化一维数组(3). 使用一维数组3. 二维数组(1). 创建二维数组(2). 初始化二维数组(3). 使用二维数组4. 对数组的基本操作(1). 遍历数组(2). 对数组进行排序...

    1. 数组概述

    Java语言中的数组是一种引用数据类型。不属于基本数据类型。数组的父类是Object
    在这里插入图片描述

    • 数组实际上是一个容器,可以容纳多个元素(数组是相同类型数据的有序集合)
    • 数组当中可以存储“基本数据类型”的数据,也可以存储“引用数据类型”的数据
    • 因为数组是引用数据类型,所以数组对象是在堆内存当中
    • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们。

    1.1 数组内存图

    • 数组当中如果存储的是“Java对象”的话,实际上存储的是对象的“引用(内存地址)”,数组不能直接存储java对象
    • 数组一旦创建,在java中规定,长度不可变
      在这里插入图片描述

    数组存储元素的特点:

    • 数组在内存方面存储的时候,数组中的元素内存地址(存储的每一个元素都是有规则的挨着排列的)是连续的。内存地址连续
    • 数组实际上是一种简单的数据结构
      在这里插入图片描述

    所有的数组都是拿“第一个小方框的内存地址”作为整个数组对象的内存地址。(数组中首元素的内存地址作为整个数组对象的内存地址)

    原因:数组存储元素的时候,内存地址是连续的,知道了第一个元素的内存地址,
          可以算出第二个,以此类推,算出所有的元素内存地址
    

    在这里插入图片描述

    1.2 数组的分类

    • 所有的数组对象都有length属性(java自带的)用来获取数组中元素的个数
      在这里插入图片描述

    1.3 数组的四个基本特点

    • 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的

    • 其元素必须是相同类型,不允许出现混合类型

        例如:int类型数组只能存储int类型,Person类型数组只能存储Person类型
      
    • 数组中的元素可以是任何数据类型,包括基本类型和引用类型

    • 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相对于该对象的成员变量。

    数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的

    1.4 数组边界

    在这里插入图片描述

    • 数组中每一个元素都是有下标的,下标从0开始,以1递增,最后一个元素的下标是:length-1
    • 下标的合法区间:[0,length-1],如果越界就会报错;
    • 我们对数组中的元素进行存取的时候,都需要通过下标来进行
    public class ArrayDemo03 {
        public static void main(String[] args) {
            int[] a = new int[2];
            System.out.println(a[2]);
        }
    }
    

    java.lang.ArrayIndexOutOfBoundsException:数组下标越界异常

    小结

    • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
    • 数组也是对象。数组元素相对于对象的成员变量
    • 数组长度是确定的,不可变的。如果越界,则报错ArrayIndexOutOfBounds

    1.5 数组这种数据结构的优缺点?

    1.5.1 优点

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

    • 原因一:每一个元素的内存地址在空间存储上是连续的

    • 原因二:每一个元素类型相同,所以占用空间大小一样

    • 原因三:知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率最高的

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

    1.5.2 缺点

    • 第一:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候,效率较低,因为随机增删元素会涉及到后面元素统一向前或者向后位移的操作
    • 第二:数组不能存储大数据量,因为很难在内存空间上找到一块特别大的连续的内存空间

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

    2. 一维数组

    2.1 声明一维数组

    首先必须声明数组变量,才能在程序中使用数组。

    下面是声明数组变量的语法:

    dataType[] arrayRefVar;	//首选的方法
    	int[] array1
    	double[] array2
    	boolean[] array3
    	String[] array3
    	Object[] array5
    

    dataType arrayRefVar[];	//效果相同,但不是首选方法
    

    2.2 创建一维数组

    声明完数组之后对数据进行创建,分配内存空间

    arrayRefVar = new dataType[空间大小];
    

    Java语言也可以使用new操作符将声明和创建二合一创建数组,语法如下:

    dataType[] arrayRedVar = new dataType[arraySize];
    

    数组的元素是通过索引访问的,数组索引从0开始

    获取素组的长度:

    arrays.length
    
    代码里面声明创建数组
    
    package com.pudding.array;
    
    public class ArrayDemo01 {
        //变量的类型    变量的名字  = 变量的值;
        //数组类型
        public static void main(String[] args) {
            int[] nums;  //1. 声明一个数组
    //        int nums[];
    
            //分配空间:这里面可以存放10个int类型的数字
            nums = new int[10]; //2. 创建数组
    
            //声明和创建合二为一
    //        int[] nums = new int[10];
    
            //3. 给数组元素中赋值
            nums[0] = 1;
            nums[1] = 2;
            nums[2] = 3;
            nums[3] = 4;
            nums[4] = 5;
            nums[5] = 6;
            nums[6] = 7;
            nums[7] = 8;
            nums[8] = 9;
            nums[9] = 10;
    
            //计算所有元素的和
            int sum = 0;
    
            //获取数组长度:arrays.length
            for (int i = 0; i < nums.length; i++) {
                sum = sum + nums[i];
            }
    
            System.out.println("总和为:"+sum);
        }
    }
    
    

    在这里插入图片描述

    2.3 初始化一维数组

    1. Java内存分析:

    在这里插入图片描述

    在这里插入图片描述

    2. 三种初始化状态:

    1. 静态初始化:

    int[] a = {1,2,3};
    Man[] mans = {new Man(1,1), new Man(2,2)}; 
    

    C++风格和Java风格:

    C++风格不建议使用:int a[] = {1,100,10,20,55}; 
    Java风格:		  int[] a = {1,100,10,20,55}; 
    
    public class ArrayTest01 {
        public static void main(String[] args) {
            //声明一个int类型的数组,使用静态初始化的方式
            int[] a = {1,100,10,20,55,689};
            //所有的数组对象都有length属性
            System.out.println("数组中元素的个数"+a.length);
            //数组中每一个元素都有下标
            //通过下标对数组中的元素进行存和取
            //取(读)
            System.out.println("第一个元素 = "+a[0]);
            System.out.println("最后一个元素 = "+a[a.length - 1]);
    
            //存(改)
            //把第一个元素修改为111
            a[0] = 111;
            //把最后一个元素修改为0
            a[a.length-1] = 0;
    
            System.out.println("第一个元素 = "+a[0]);
            System.out.println("最后一个元素 = "+a[5]);
    
            //一维数组怎么遍历?
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]); //i是0到5,是下标
            }
    
            //下标为6表示第7个元素,下标越界了,会出现什么异常?
    //        System.out.println(a[6]); //ArrayIndexOutOfBoundsException 数组下标越界异常
    
            //从最后一个元素遍历到第一个元素
            for (int i = a.length - 1; i > 0; i--) {
                System.out.println("颠倒顺序输出-->" + a[i]);
            }
        }
    }
    
    

    2. 动态初始化:

    int[] a = new int[2]; //这个的2表示数组的元素个数
    					  //初始化一个5个长度的int类型数组,每个元素默认值0
    a[0] = 1;
    a[1] = 2;
    
    String[] names = new String[6]; //初始化6个长度的String类型数组,每个元素默认值null
    
    public class ArrayTest02 {
        public static void main(String[] args) {
            //声明/定义一个数组,采用动态初始化的方式创建
            int[] a = new int[4]; //创建长度为4的int数组,数组中每一个元素的默认值是0
            //遍历数组
            for (int i = 0; i < a.length; i++) {
                System.out.println("数组中下标为:"+i+"的元素为"+a[i]);
            }
    
    		//后期赋值,注意下标别越界
            a[0] = 1;
            a[1] = 2;
            a[2] = 3;
            a[3] = 4;
    
            //初始化一个Object类型的数组,采用动态初始化方式
            Object[] obj = new Object[3]; //3个长度,动态初始化,所有每个默认值是null
            for (int i = 0; i < obj.length; i++) {
                System.out.println(obj[i]);
            }
    
            //采用静态初始化数组的方式
            Object o1 = new Object();
            Object o2 = new Object();
            Object o3 = new Object();
            Object[] objects = {o1,o2,o3};
            for (int i = 0; i < objects.length; i++) {
                System.out.println(objects[i]); //println默认调用toString方法,
                                                // 输出java.lang.Object@3f99bd52
                                                //java.lang.Object@4f023edb
                                                //java.lang.Object@3a71f4dd
            }
            //等价于
            //Object[] object = {new Object(),new Object(), new Object()};
    
            System.out.println("=========================");
    
            String[] strs = new String[3];  //动态初始化数组
            for (int i = 0; i < strs.length; i++) {
                System.out.println(strs[i]);
            }
    
            //采用静态初始化的方式
            String[] strs2 = {"abc","def","xyz"};
            for (int i = 0; i < strs2.length; i++) {
                System.out.println(strs2[i]);
            }
        }
    }
    

    在这里插入图片描述

    3. 数组的默认初始化

    数组是引用类型,它的元素相对于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。

    /*
    关于每个类型的默认值还有印象?
        数据类型        默认值
        --------------------
        byte            0
        short           0
        int             0
        long            0L
        float           0.0F
        double          0.0
        boolean         false
        char            \u0000
        引用数据类型     null
     */
    
    public class ArrayDemo02 {
        public static void main(String[] args) {
            //静态初始化:创建+赋值 (这个是基本类型)
            int[] a = {1,2,3,4,5,6,7,8};
            System.out.println(a[0]);
    
            //动态初始化: 包含默认初始化
            int[] b = new int[10];
            b[0] = 10;
            System.out.println(b[0]);
            System.out.println(b[1]);  //默认初始化中的值都是0
            System.out.println(b[2]);
            System.out.println(b[3]);
        }
    }
    
    

    什么时候采用静态初始化,什么时候采用动态初始化?

    • 当你创建数组的时候,确定数组中存储哪些具体的元素的时候,采用静态初始化方式
    • 当你创建数组的时候,不确定将来数组中存储哪些数据,你可以采用动态初始化的方式,预先分配内存空间,之后再赋值

    2.4 使用一维数组

    1. 一维数组的遍历

    public class ArreyDemo04 {
        public static void main(String[] args) {
            int[] arrays = {1,2,3,4,5};
    
            //打印全部的数组元素
            for (int i=0; i<arrays.length; i++){
                System.out.println(arrays[i]);
            }
            System.out.println("===============");
            //计算所有元素的和
            int sum = 0;
            for (int i = 0; i < arrays.length; i++) {
                sum += arrays[i];
            }
            System.out.println("sum = "+sum);
            System.out.println("===============");
    
            //查找最大元素
            int max = arrays[0];
    
            for (int i = 1; i < arrays.length; i++) {
                if (arrays[i] > max){
                    max = arrays[i];
                }
            }
            System.out.println("max = "+max);
    
        }
    }
    
    

    For-Each循环

    public class ArrayDemo05 {
        public static void main(String[] args) {
            int[] arrays = {1,2,3,4,5};
    
            for (int array : arrays) {  //增强型的for循环,JDK1.5之后,没有下标
                System.out.println(array);
            }
        }
    }
    

    2. 数组作为方法的参数类型进行传参

    数组作为方法的参数举例理解

    package com.pudding.array;
    
    public class ArrayDemo05 {
        public static void main(String[] args) {
            int[] arrays = {1,2,3,4,5};
    
            int[] reverse = reverse(arrays);
            printArray(reverse);
        }
    
        //打印数组元素
        public static void printArray(int[] arrays){
            for (int i = 0; i < arrays.length; i++) {
                System.out.print(arrays[i]+" ");
            }
        }
    
        //反转数组
        public static int[] reverse(int[] arrays){
            int[] result = new int[arrays.length];
    
            //反转的操作
            for (int i = 0,j=result.length-1; i < arrays.length; i++,j--) {
                result[i] = arrays[j];
            }
    
            return result;
        }
    
    }
    

    当一个方法上,参数类型是一个数组的时候,我们可以采用以下基本传参方式。

    public class ArrayTest03 {
        //main方法的编写方式,还可以采用C++的语法格式
        public static void main(String args[]) {
            //调用方法时传一个数组
            int[] x = {1,2,3,4};
            printArray(x);
    
            //创建String数组
            String[] strs= {"abc","def","hehe","haha"};
            printArray(strs);
    
            //动态创建数组
            String[] strArray = new String[10];
            printArray(strArray); //10个null
    
            System.out.println("===============");
            printArray(new String[3]);
            System.out.println("****************");
            printArray(new int[4]);
        }
    
        public static void printArray(int[] array){
            for (int i = 0; i < array.length; i++) {
                System.out.println(array[i]);
            }
        }
    
        public static void printArray(String[] args){
            for (int i = 0; i < args.length; i++) {
                System.out.println("String数组中的元素:"+args[i]);
            }
        }
    }
    
    

    当一个方法的参数是一个数组的时候,我们还可以采用这种方式传参,采用静态初始化直接传参。

    public class ArrayTest04 {
        public static void main(String[] args) {
            //静态初始化一维数组
            int[] a = {1,2,3};
            printArray(a);
    
            System.out.println("============");
            //没有这种语法
            //printArray({1,2,3});
            //如果直接传递一个静态数组的话,语法必须这样写
            printArray(new int[]{1,2,3});
    
            //动态初始化一维数组
            int[] a2 = new int[4];
            printArray(a2);
    
            System.out.println("=========");
            printArray(new int[2]);
        }
    
        //使用静态方法方便啊,不需要new对象了
        public static void printArray(int[] array){
            for (int i = 0; i < array.length; i++) {
                System.out.println(array[i]);
            }
        }
    }
    
    

    3. main方法上面的"String[ ] args"有什么用?

    分析 一下:谁负责调用main方法(JVM)

    • JVM调用main方法的时候,会自动传一个String数组过来
    public class ArrayTest05 {
        //这个方法程序员负责写出来,JVM负责调用的时候一定会传入一个String数组过来
        public static void main(String[] args) {
            //JVM默认传递过来的这个数组对象长度:默认0
            //通过测试得出:args不是null
            System.out.println("JVM给传递过来的String数组参数,他这个数组长度是:"+args.length);
    
            /*
            //类似:以下代码表示的含义:数组对象创建了,但还是数组中没有任何数据
            //String[] strs = new String[0];
            String[] strs = {}; //静态初始化,里面没有东西
            printlength(strs);
    
            String[] strs2 = new String[1];
            System.out.println(strs2[0]); //默认初始化里面的一个数据为null
            */
    
            //遍历数组
            for (int i = 0; i < args.length; i++) {
                System.out.println(args[i]);
            }
        }
    
        public static void printlength(String[] args){
            System.out.println(args.length); //长度为0
        }
    }
    

    这个数组什么时候里面会有值?

    • 其实这个数组是留给用户的,用户可以在控制台上输入参数,这个参数自动会转换为"String[] args"
    • 例如这样的程序:java ArrayTest05 abc def xyz
    • 那么这个时候JVM会自动将"abc def xyz"通过空格的方式进行分离,分离完成之后,自动放到"String[] args"数组当中
    • 所以main方法上面的String[] args数组主要是用来接收用户输入参数的
    • 把abc def xyz 转换为字符串数组:{“abc”,“def”,“xyz”}

    CMD中
    在这里插入图片描述
    IDEA中
    在这里插入图片描述
    模拟一个系统,假设这个系统要使用,必须输入用户名和密码

    public class ArrayTest06 {
        //用户名和密码输入到String[] args数组当中
        public static void main(String[] args) {
            if (args.length != 2){
                System.out.println("使用该系统时请输入程序参数,参数中包括用户名和密码信息,例如:zhangsan 123");
                return;
            }
    
            //程序执行到此处说明用户确实提供了用户名和密码
            //接下来你应该判断用户名和密码是否正确
            //取出用户名
            String username = args[0];
            //取出密码
            String password = args[1];
    
            //假设用户名是admin,密码是123的时候表示登录成功,其他一律失败
            //判断两个字符串是否相等,需要使用equals方法
            //if (username.equals("admin") && password.equals("123")){
            //下面编写可以避免空指针异常,即使username和password都是null也不会出现空指针异常
            if ("admin".equals(username) && "123".equals(password)){
                System.out.println("登录成功,欢迎["+username+"]回来");
            } else {
                System.out.println("验证失败,用户名不存在或者密码错误");
            }
        }
    }
    

    非重点:以后一般都是有界面的,用户可以在界面上输入用户名和密码等参数信息。

    4. 数组中存储引用数据类型

    一维数组的深入,数组中存储的类型为:引用数据类型

    • 对于数组来说,实际上只能存储java对象的"内存地址",数组中存储的每个元素是“引用”。
    package com.array;
    
    public class ArrayTest07 {
        public static void main(String[] args) {
    
            //array是一个数组
            //array[0] 是数组中的一个元素
            int[] array = {1,2,3};
            for (int i = 0; i < array.length; i++) {
                int temp = array[i];
                System.out.println(temp);
            }
    
            //创建一个Animal类型的数组
            Animal a1 = new Animal();
            Animal a2 = new Animal();
            Animal[] animals = {a1,a2};
    
            //对Animal数组进行遍历
            for (int i = 0; i < animals.length; i++) {
                /*
                Animal a = animals[i];
                a.move();
                */
                //代码合并
                animals[i].move(); //这个move()方法不是数组的,是数组当中Animal对象的move()方法
            }
    
            //动态初始化一个长度为2的Animal类型数组
            Animal[] ans = new Animal[2];
            //创建一个Animal对象,放到数组里的第一个盒子中
            ans[0] = new Animal();
    
            //Animal数组中只能存放Animal类型,不能存放Product类型
            //ans[1] = new Product()
    
            //Animal数组中可以存放Cat类型的数据,因为Cat是一个Animal
            //Cat是Animal子类
            ans[1] = new Cat();
    
            //创建一个Animal类型的数组,数组中存储Cat和Brid
            Animal[] anis = {new Cat(), new Bird()}; //该数组中存储了两个对象的内存地址
            for (int i = 0; i < anis.length; i++) {
    
                /*
                //这个取出来的可能是Cat,也可能是Bird,不过肯定是一个Animal
                //如果调用的方法是父类中存在的方法不需要向下转型,直接使用父类型引用调用即可
                Animal an1 = anis[i];
                an1.move();
                */
    
                //Animal中没有sing()方法
                //anis[i].sing();
    
                //调用子对象中特有的方法的话,需要向下转型
                if (anis[i] instanceof Cat){
                    Cat cat = (Cat)anis[i];
                    cat.catchMouse();
                } else if (anis[i] instanceof Bird){
                    Bird bird = (Bird)anis[i];
                    bird.sing();
                }
    
            }
    
        }
    }
    
    class Animal{
        public void move(){
            System.out.println("Animal move...");
        }
    }
    
    //商品类
    class Product{
    
    }
    
    //子类猫
    class Cat extends Animal{
        public void move(){
            System.out.println("Cat move...");
        }
        //特有的方法
        public void catchMouse(){
            System.out.println("猫抓老鼠。。");
        }
    }
    
    //Bird子类
    class Bird extends Animal{
        public void move(){
            System.out.println("Bird fly....");
        }
        //特有的方法
        public void sing(){
            System.out.println("鸟儿在歌唱");
        }
    }
    
    

    5. 数组扩容

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

    • java中数组的扩容是:先新建一个大容量的数组,然后将小容量的数组中的数据一个一个拷贝到大数组当中,小数组对象被垃圾回收。
    • 结论:数组扩容效率比较低,因为涉及到拷贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。
    • 可以在创建数组对象的时候预估以下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率
      在这里插入图片描述
      在这里插入图片描述

    6. 数组拷贝

    package com.array;
    
    public class ArrayTest08 {
        public static void main(String[] args) {
            //java中的数组是怎么进行拷贝的?
            //System.arraycopy(5个参数);
    
            //拷贝源(从数组中拷贝)
            int[] src = {1,11,22,3,4};
    
            //拷贝目标(拷贝到这个目标数组上)
            int[] dest = new int[20]; //动态初始化一个长度为20的数组,每一个元素的默认值为0
    
            /*
            //调用JDK,System类中的arraycopy方法,来完成数组的拷贝
            System.arraycopy(src, 1, dest, 3, 2);
    
            //遍历目标数组
            for (int i = 0; i < dest.length; i++) {
                System.out.println(dest[i]); //0 0 0 11 22 0 ...0
            }
            */
    
            System.arraycopy(src, 0, dest, 0, src.length);
            for (int i = 0; i < dest.length; i++) {
                System.out.println(dest[i]);
            }
    
            //数组中存储的元素是引用类型的话,也可以拷贝
            String[] strs = {"hello","world","study","java","oracle","mysql","jdbc"};//字符串数组
            String[] newStrs = new String[20];
            System.arraycopy(strs,0,newStrs,0,strs.length);
    
            for (int i = 0; i < newStrs.length; i++) {
                System.out.println(newStrs[i]); //hello world study java oracle mysql jdbc null...
            }
    
            Object[] objs = {new Object(), new Object(), new Object()};
            Object[] newObjs = new Object[5];
            //这里拷贝的时候,是拷贝对象的地址
            System.arraycopy(objs,0,newObjs,0,objs.length);
            for (int i = 0; i < newObjs.length; i++) {
                System.out.println(newObjs[i]); //默认调用toString方法
                /*
                输出结果:
                java.lang.Object@3f99bd52
                java.lang.Object@4f023edb
                java.lang.Object@3a71f4dd
                null
                null
                 */
            }
    
        }
    }
    
    

    在这里插入图片描述

    3. 二维数组

    多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,特殊在,这个一维数组当中的每一个元素都是一个一维数组

    • 三位数组是一个特殊的二维数组,特殊在这个二维数组中每一个元素都是一个一维数组
    • 实际开发中使用最多的就是一维数组,二维数组很少使用,三位数组几乎不用

    在这里插入图片描述
    在这里插入图片描述

    (1). 创建二维数组

    int a[][] = new int[2][5]
    

    以上二维数组a可以看成一个两行五列的数组

    package com.pudding.array;
    
    public class ArrayDemo06 {
        public static void main(String[] args) {
    
            //[4][2]
            /*
                1,2     array[0]
                2,3     array[1]
                3,4     array[2]
                4,5     array[3]
             */
            int[][] array = {{1,2},{2,3},{3,4},{4,5}};
    
            printArray(array[0]);               //打印的是二维数组中的第一行的一维数组
    
            System.out.println();
            System.out.println(array[0][0]);    //二维数组的第一行第一列的值
            System.out.println(array[0][1]);
    
            for (int i = 0; i < array.length; i++) {        //外面空间数组长度
                for (int j = 0; j < array[i].length; j++) { //每一个一维数组的长度
                    System.out.println(array[i][j]);
                }
            }
    
    
        }
    
        //打印数组元素
        public static void printArray(int[] arrays){
            for (int i = 0; i < arrays.length; i++) {
                System.out.print(arrays[i]+" ");
            }
        }
    }
    
    

    (2). 初始化二维数组

    1. 二维数组的静态初始化和动态初始化

    静态初始化

    int[][] arr = {
    				{112,2.3},
    				{3,43},
    				{34,23,3,5}
    			};
    			
    Object[][] arr = {
    					{new Object(),new Object()},
    					{new Object(),new Object(),new Object()},
    					{new Object(),new Object()}
    				};
    

    动态初始化

    int[][] arr = new int[3][4];   //三行四列
    Object[][] arr = new Object[4][4]; //四行四列
    Animal[][] arr = new Animal[2][2];
    //animal类型数组,里面可以存储animal类型对象,以及animal类型子类型
    

    2. 二维数组length属性

    package com.array;
    
    public class ArrayTest09 {
        public static void main(String[] args) {
            //一维数组
            int[] array = {100,200,300};
            System.out.println(array.length); //3个
    
            //二维数组
            //以下代码当中:里面是4个一维数组
            int[][] a = {
                    {100,200,300},
                    {30,20,40,50,60},
                    {6,7,9,1},
                    {0}
            };
            System.out.println(a.length); //4个元素
            System.out.println(a[0].length); //3个元素
            System.out.println(a[1].length); //5个元素
            System.out.println(a[3].length); //1个元素
        }
    }
    
    

    (3). 使用二维数组

    1. 二维数组的元素访问

    package com.array;
    
    /*
    关于二维数组中元素的:读和该
        a[二维数组中的一维数组的下标][一维数组的下标]
        a[0][0]:表示第一个一维数组中的第一个元素
    
        注意对于a[3][100]来说,其中a[3]是一个整体,[100]是前面a[3]执行结束的结果然后再下标100.
     */
    public class ArrayTest10 {
        public static void main(String[] args) {
            //二维数组
            int[][] a = {
                    {11,23,54},
                    {100,23,432,234},
                    {0}
            };
    
    
            //请取出以上二维数组中的第一个一维数组
            int[] 我是第1个一维数组 = a[0];
            int 我是第1个一维数组中的第1个元素 = 我是第1个一维数组[0];
            System.out.println(我是第1个一维数组中的第1个元素); //11
    
            //合并以上代码
            System.out.println(a[0][0]); //11
            
            //注意别越界
            // System.out.println(a[2][1]); //ArrayIndexOutOfBoundsException
    
            //取出第二个一维数组当中第三个元素
            System.out.println("第二个数组中第三个元素:"+a[1][2]); //432
    
            //改
            a[2][0] = 11111;
            System.out.println(a[2][0]); //11111
        }
    }
    
    

    2. 二维数组的遍历

    package com.array;
    
    public class ArrayTest11 {
        public static void main(String[] args) {
            //二维数组
            String[][] array = {
                    {"java","oracle","c++","c#"},
                    {"张三","李四","王五"},
                    {"lucy","jack","rose"}
            };
    
            //遍历二维数组
            for (int i = 0; i < array.length; i++) { //外层循环3次(负责纵向,也就是外面的一维数组)
                /*
                String[] 一维数组 = array[i];
                //负责遍历一维数组
                for (int j = 0; j < 一维数组.length; j++) {
                    System.out.println(一维数组[j]+"");
                }
                */
                
                //合并代码
                //内存循环负责输出一行,负责遍历二维数组里面的一维数组
                for (int j = 0; j < array[i].length; j++) {
                    System.out.print(array[i][j]+" ");
                }
    
                //换行
                System.out.println();
            }
        }
    }
    
    

    3. 方法的参数是一个二维数组

    package com.array;
    
    /*
    * 动态初始化二维数组
    * */
    public class ArrayTest12 {
        public static void main(String[] args) {
            //3行4列:3个一维数组,每一个一维数组当中4个元素
            int[][] array = new int[3][4];
    
            //二维数组遍历
            /*
            for (int i = 0; i < array.length; i++) { //循环3次
                for (int j = 0; j < array[i].length; j++) { //循环4次
                    System.out.print(array[i][j]+" ");
                }
                System.out.println();
            }
            */
    
            //静态初始化
            int[][] a = {
                    {1,2,3,4},
                    {4,5,6,76},
                    {1,23,4}
            };
            printArray(a);
    
            //没有这种语法
            //printArray({{1,2,3,4}, {4,5,6,76}, {1,23,4}});
    
            //可以这样写
            printArray(new int[][]{{1,2,3,4}, {4,5,6,76}, {1,23,4}});
        }
    
        public static void printArray(int[][] array){
            //二维数组遍历
            for (int i = 0; i < array.length; i++) { //循环3次
                for (int j = 0; j < array[i].length; j++) { //循环4次
                    System.out.print(array[i][j]+" ");
                }
                System.out.println();
            }
        }
    }
    
    

    4. 数组模拟题目练习

    (1). 数组模拟栈数据结构

    编写程序,使用一维数组,模拟数据结构

    要求:
        1. 这个栈可以存储java中的任何引用类型的数据
        2. 在栈中提供push方法模拟压栈(栈满了,要有提示信息)、
        3. 在栈中提供pop方法模拟弹栈(栈空了,也要有提示信息)
        4. 编写测试程序,new栈对象,调用push、pop方法来模拟压栈弹栈的动作
    
    • Object[]这是一个万能的口袋,这个口袋中可以装任何引用数据类型的数据

    5. Arrays类

    4.1 概述

    数组工具类java.util.Arrays

    由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作

    Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而不用使用对象来调用(注意:是不用,而不是不能)

    4.2 Arrays具有以下常用的功能

    • 给数组赋值:通过fill方法
    • 对数组排序:通过sort方法,按升序
    • 比较数组:通过equals方法比较数组中元素值是否相等
    • 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作
    package com.pudding.array;
    
    import java.util.Arrays;
    
    public class ArrayDemo07 {
        public static void main(String[] args) {
    
            int[] a = {1,23,43,6,12390,1323,23};
    
            System.out.println(a);  //对象的哈希code[I@154617c
    
            //打印数组元素Arrays.toString
            System.out.println(Arrays.toString(a));
            printArray(a);
    
            Arrays.sort(a); //数组进行排序:  顺序
            System.out.println(Arrays.toString(a));
    
            Arrays.fill(a,2,4,0);   //数组填充(将下标2-4填充为0)
            System.out.println(Arrays.toString(a));
    
        }
    
        //重复造轮子
        public static void printArray(int[] a){
            for (int i = 0; i < a.length; i++) {
                if (i==0){
                    System.out.print("[");
                }
    
                if (i==a.length-1){
                    System.out.print(a[i]+"]");
                }else {
                    System.out.print(a[i]+", ");
                }
            }
        }
    }
    
    

    5. 对数组的基本操作

    (1). 遍历数组

    (2). 对数组进行排序

    十大经典排序算法

    5.2.1 冒泡排序

    冒泡排序无疑是最为出名的排序算法之一,总共有八大排序

    在这里插入图片描述
    冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知。

    我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度0(n2)

    冒泡排序
    
    package com.pudding.array;
    
    import java.util.Arrays;
    
    public class ArrayDemo08 {
        public static void main(String[] args) {
            int[] a = {1,2,6,23,12,33,-6};
            int[] sort = sort(a);   //调用完我们自己写的排序方法以后,返回一个排序后的数组
    
            System.out.println(Arrays.toString(sort));
    
        }
    
        //冒泡排序
        //1. 比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
        //2. 每一次比较,都会产生出一个最大,或者最小的数字;
        //3. 下一轮则可以少一次排序
        //4. 依次循环,直到结束!
    
        public static int[] sort(int[] array){
            //临时变量
            int temp = 0;
    
            //外层循环,判断我们这个要走多少次;
            for (int i = 0; i < array.length-1; i++) {
                //内存循环,比较判断两个数,如果第一个数比第二个数大,则交换位置
                for (int j = 0; j < array.length-1-i; j++) {
                    if (array[j+1] < array[j]){
                        temp = array[j+1];
                        array[j+1] = array[j];
                        array[j] = temp;
                    }
                }
            }
    
            return array;
    
        }
    }
    

    (3). 填充替换数组元素

    (4). 复制数组

    (5). 数组查询

    (6). 稀疏数组

    需求:编写五子棋游戏中,有存盘退出和续上盘的功能
    在这里插入图片描述
    其中黑子代表1,白子代表2,因为该二维数组的很多默认值0,因此记录了很多没有意义的数据。

    解决方式:通过稀疏数组(压缩)

    6.1 稀疏数组的介绍

    当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

    稀疏数组的处理方式:

    • 记录数组一共有几行几列,有多少个不同值
    • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

    如下图:左边是原始数组,右边是稀疏数组
    在这里插入图片描述

    6.2 稀疏数组的应用

    package com.pudding.array;
    
    public class ArrayDemo09 {
        public static void main(String[] args) {
            //1. 创建一个二维数组11*11, 0:没有棋子,1:黑棋,2:白棋
    
            int[][] array1 = new int[11][11];
            array1[1][2] = 1;
            array1[2][3] = 2;
            //输出原始的数组
            System.out.println("输出原始的数组");
    
            for (int[] ints : array1) {
                for (int anInt : ints) {
                    System.out.print(anInt+"\t");
                }
                System.out.println();
            }
    
            System.out.println("===================");
            //转换为稀疏数组保存
            //获取有效值的个数
            int sum = 0;
            for (int i = 0; i < 11; i++) {
                for (int j = 0; j < 11; j++) {
                    if (array1[i][j]!=0){
                        sum++;
                    }
                }
            }
            System.out.println("有效值的个数:"+sum);
    
            //1. 创建一个稀疏数组的数组
            int[][] array2 = new int[sum+1][3];
            array2[0][0] = 11;  //代表数组有多少行
            array2[0][1] = 11;  //代表数组有多少列
            array2[0][2] = sum; //代表有效值的个数
    
            //遍历原来的二维数组,将非零的值存放到稀疏数组中
            int count = 0;
            for (int i = 0; i < array1.length; i++) {
                for (int j = 0; j < array1[i].length; j++) {
                    if (array1[i][j]!=0){
                        count++;
                        array2[count][0] = i;   //获取原数组位置赋值给稀疏数组的第count行第1列
                        array2[count][1] = j;
                        array2[count][2] = array1[i][j];//或者原数组的值赋值给稀疏数组的第count行第3列
                    }
                }
            }
    
            //输出稀疏数组
            System.out.println("稀疏数组");
    
            for (int i = 0; i < array2.length; i++) {
                System.out.println(array2[i][0]+"\t"
                        +array2[i][1]+"\t"
                        +array2[i][2]+"\t");
    
            }
    
            System.out.println("===================");
            System.out.println("还原数组");
            //1. 读取稀疏数组的值
            int[][] array3 = new int[array2[0][0]][array2[0][1]];
    
            //2. 给其中的元素还原它的值
            for (int i = 1; i < array2.length; i++) {
                array3[array2[i][0]][array2[i][1]] = array2[i][2];
            }
    
            //打印
            System.out.println("输出还原的数组");
    
            for (int[] ints : array3) {
                for (int anInt : ints) {
                    System.out.print(anInt+"\t");
                }
                System.out.println();
            }
        }
    }
    
    结果如下:
    
    输出原始的数组
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	1	0	0	0	0	0	0	0	0	
    0	0	0	2	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    ===================
    有效值的个数:2
    稀疏数组
    11	11	2	
    1	2	1	
    2	3	2	
    ===================
    还原数组
    输出还原的数组
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	1	0	0	0	0	0	0	0	0	
    0	0	0	2	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0
    
    展开全文
  • 一、数组模拟环形队列说明 1.这是对前面的数组模拟队列的优化,充分利用数组。因此将数组看看成一个环形的(通过取模的方式来实现即可)。...import java.util.Scanner; public class CircleArrayQueu

    Java使用数组模拟环形队列

    一、数组模拟环形队列说明
    1.这是对前面的数组模拟队列的优化,充分利用数组。因此将数组看看成一个环形的(通过取模的方式来实现即可)。
    2.对环形队列进行分析说明:
    (1)尾索引的下一个为头索引时表示队列已满,即将队列容量空出一个作为一个约定,这个在做队列满的时候需要注意(rear+1)%maxSize=front为队列满的判定条件
    (2)rear=front还是环形队列为空的判定条件
    二、代码实现

    import java.util.Scanner;
    
    public class CircleArrayQueueDemo {
    
        public static void main(String[] args) {
            //测试一把
            System.out.println("测试数组模拟环形队列的案例~~");
    
            //创建一个数组队列
            CircleArray circleArray=new CircleArray(4);//说明4:其队列的有效数据最大为3
            char key=' ';   //接收用户输入
            Scanner scanner=new Scanner(System.in);
            boolean loop=true;
            //输出一个菜单
            while(loop){
                System.out.println("s(show):显示队列");
                System.out.println("e(exit):退出程序");
                System.out.println("a(add):添加数据到队列");
                System.out.println("g(get):从队列取出数据");
                System.out.println("h(head):查看队列头的数据");
                key=scanner.next().charAt(0); //接收一个字符
                switch (key) {
                    case 's':
                        circleArray.showQueue();
                        break;
    
                    case 'e':
                        scanner.close();
                        loop=false;
                        break;
    
                    case 'a':
                        System.out.println("请输入一个数:");
                        int value=scanner.nextInt();
                        circleArray.addQueue(value);
                        break;
    
                    case 'g':
                        try {
                            int res=circleArray.getQueue();
                            System.out.printf("取出的数据是%d\n",res);
                        }
                        catch (Exception e) {
                            // TODO: handle exception
                            System.out.println(e.getMessage());
                        }
                        break;
    
                    case 'h'://查看队列头的数据
                        try {
                            int res=circleArray.headQueue();
                            System.out.printf("输出队列头的数据是%d\n",res);
                        }
                        catch (Exception e) {
                            // TODO: handle exception
                            System.out.println(e.getMessage());
                        }
                        break;
    
                    default:
                        break;
                }
            }
            System.out.println("程序退出");
    
        }
    
    }
    //创建一个模拟环形数组的类
    class CircleArray{
    
        private int maxSize;//表示数组的最大容量
        //front变量的含义做一个调整:front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值为0
        private int front;
        //rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置,目的是:希望空出一个空间作为约定,real的初始值为0
        private int rear;
        private int[] arr;//该数据用于存放数据,模拟队列
        
    	//构造器
        public CircleArray(int arrMaxSize){
        
            maxSize=arrMaxSize;
            arr=new int[maxSize];
            front=0;
            rear=0;
        }
    
        //判断队列是否满
        public boolean isFull() {
            return (rear+1) % maxSize==front;
        }
    
        //判断队列是否为空
        public boolean isEmpty() {
            return front==rear;//当队列的头部和队列的尾部相等的时候,此时队列就是为空的
        }
    
        //添加数据到队列中
        public void addQueue(int n) {
            //判断队列是否满了
            if (isFull()) {
                System.out.println("队列已满,不能加入数据!");
                return;
            }
            //直接将数据加入就可以了
            arr[rear]=n;
            //将real后移
            rear=(rear+1) % maxSize;
        }
    
        //获取队列的数据,数据出队列
        public int getQueue() {
            //判断队列是否为空,队列为空不能出队列
            if (isEmpty()) {
                throw new RuntimeException("队列空,不能取数据");
            }
    
            //这里需要分析出front是指向队列的第一个元素
            //1.先把front对应的值保存到一个临时变量中
            //2.将front后移,考虑取模
            //3.将临时保存的变量返回
            int value=arr[front];
            front=(front+1) % maxSize;
            return value;
        }
    
        //显示队列的所有数据
        public void showQueue() {
            //遍历数组
            if (isEmpty()) {
                System.out.println("队列是空的,没有数据~");
                return;
            }
            //思路:从front开始遍历,遍历多少个元素
            for(int i=front;i<front + size();i++){
                System.out.printf("arr[%d]=%d\n",i % maxSize,arr[i % maxSize]);
            }
        }
    
        //求出当前队列有效数据的个数,否则无法遍历队列的所有数据
        public int size(){
            //比如rear=1,front=0,maxSize=3 此时有效数字为1
            return (rear+maxSize-front) % maxSize;
        }
    
        //显示队列的头数据,注意这不是取出头部数据
        public int headQueue(){
            //判断队列是否为空
            if (isEmpty()) {
                throw new RuntimeException("队列是空的,没有数据~");
            }
            return arr[front];
        }
    }
    

    三、测试代码,如下图所示:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • java数组

    2021-04-16 19:56:35
    1、Java语言当中的数组是一种引用数据类型,数组的父类型是Object 2、数组实际上是一个容器,可以同时容纳多个元素(数组是一个数据的集合) 3、数组当中可以存储“基本数据类型”的数据 ,也可以存储“引用数据类型...

    一、一维数组
    1、Java语言当中的数组是一种引用数据类型,数组的父类型是Object
    2、数组实际上是一个容器,可以同时容纳多个元素(数组是一个数据的集合)
    3、数组当中可以存储“基本数据类型”的数据 ,也可以存储“引用数据类型”的数据
    4、因为数组是引用数据类型,所以数组对象存储在堆内存当中。
    5、数组当中如果存储的是"java对象"的话,实际上存储的是对象的“引用(内存地址)”,数组中不能直接存储java对象
    6、java中规定,数组一旦创建,其长度不可变(数组长度不可变)
    7、数组的分类:一维数组、二维数组、多维数组(一维数组使用较多,二维数组偶尔使用)
    8、所有的数组对象都有length属性,用来获取数组中元素的个数
    9、java中的数组,要求数组中元素的类型同一,如:int类型的数组只能存储int类型的数据
    10、数组中的元素内存地址是连续的(存储的每一个元素都是有规则的挨着排列的),
    内存地址连续,这是数组存储元素的特点。数组实际上是一种简单的数据结构。
    11、所有的数组都是拿“第一个小方块的内存地址”作为整个数组对象的内存地址(数组中首元素的内存地址作为整个数组对象的内存地址)
    12、数组中每个元素都是有下标的,下标从0开始,以步长为1递增,最后一个元素的下标是:length - 1。
    下标的作用:利用下标对数组的中的元素做“存取”操作
    13、数组的优缺点:
    优点:查询/检索/查找某个下标上的元素时效率极高。可以说是查询效率最高的一种数据结构
    为什么检索效率高?
    1)每一个元素的内存地址在空间存储上是连续的
    2)每一个元素类型相同,所以占有空间大小一样
    3)知道第一个元素的内存地址,知道每一个元素占用空间的大小,知道下标,所以
    可以通过一个数学表达式计算出某个下标上元素的内存地址,直接通过内存地址定位
    元素,所以数组的检索效率是最高的。
    缺点:
    1)由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候效率极低,
    因为随机增删元素会涉及到后面元素统一向前或者向后位移的操作。
    2)数组不能存储大数据量
    原因:很难在内存空间上找到一块特别大的连续的内存空间。
    【注】对于数组中最后一个元素的增删,是没有效率影响的。
    14、一维数组声明/定义:
    语法格式:
    int[] array1;
    double[] array2;
    boolean[] array3;
    String[] array4;
    Object[] array5;
    15、数组的初始化:
    1)初始化数组有两种方式:
    方式一:静态初始化:声明的同时赋值
    语法格式:
    int[] array = {10,34,45,67,35}
    int[] array = new int[]{10,34,45,67,35}
    Object[] array = {new Object(),new Object(),new Object()}
    方式二:动态初始化:先声明,后通过数组的下标赋值
    //此处的8表示数组的大小/长度
    //初始化一个长度为8的大小的String类型的数组,每个元素的默认值为null
    String[] array = new String[8];

                Object[] array = new Object[4];
    
                //此处的10表示数组的大小/长度
               //初始化一个长度为10的大小的int类型的数组,每个元素的默认值为0
                int[] array = new int[10];
    2)静态初始化和动态初始化的使用场景:
    	 (1)当创建数组的时候,确定数组中存储哪些具体的元素时,采用静态初始化方式
    	 (2)当创建数组的时候,不确定数组中存储哪些具体的元素时,但确定数组的大小,
    		采用动态初始化方式,预先分配内存空间。
    

    16、数组越界异常(java.lang.ArrayIndexOutOfBoundsException):
    访问数组的时候超过了其允许的下标的长度,就会出现数组越界异常。

    /**
     * 以下程序测试的内容
     * 1、数组的静态初始化
     * 2、数组的动态初始化
     * 3、length方法、
     * 4、利用下标对数组的元素进行“存取”操作
     * 5、数组的遍历:1)普通for 2)foreach
     */
    
    
    public class ArrayTest01 {
        public static void main(String[] args) {
    
            //声明一个基本数据类型int类型的数组,采用静态初始化
            int[] arr1 = {1,4,5,6,7};
    
            //声明一个引用数据类型Object类型的数组,采用静态初始化
            Object obj1 = new Object();
            Object obj2 = new Object();
            Object obj3 = new Object();
            Object[] arr2 = {obj1,obj2,obj3};
    
            //上面四句代码可以写成如下形式
            //Object[] arr2 = {new Object(),new Object(),new Object()};
    
            //声明一个基本数据类型int类型的数组,采用动态初始化
            char[] arr3 = new char[4];//char的默认值为\u0000
    
            //声明一个引用数据类型Object类型的数组,采用动态初始化
            Object[] arr4 = new Object[3];
    
            //length属性的测试
            System.out.println("数组长度: "+arr1.length);
            System.out.println("数组长度: "+arr4.length);
    
            //利用下标对数组的元素进行“存取”操作
            arr1[arr1.length -1] = 9;
            arr3[0] = 'A';
            arr3[2] = 'B';
            //普通for循环遍历arr1
            for (int i = 0; i < arr1.length ; i++) {
                if (i == arr1.length-1) {
                    System.out.print("元素"+i+"==>"+arr1[i]);
                    System.out.println();
                    break;
                }
                System.out.print("元素"+i+"==>"+arr1[i]+'\t');
            }
            //普通for循环遍历arr3
            for (int i = 0; i <arr3.length ; i++) {
                System.out.println("arr3的第"+i+"个元素为:"+arr3[i]);
            }
    
            //foreach循环遍历arr4
            for (Object arr :arr4) {
                System.out.println(arr);
            }
    
            //数组越界异常
            boolean arr5[] = new boolean[]{false,true,true,false};
            System.out.println(arr5[4]);
        }
    }				 
    
    package Test;
    
    import java.util.Random;
    
    /**
     * 以下程序测试的内容:
     * 1、提供数组的正序、倒叙遍历
     * 2、随机生成数组
     * 3、数组作为方法的参数
     * 4、方法的可变参数和混合参数
     */
    public class ArrayTest02 {
        public static void main(String[] args) {
            String[] arr = new String[]{"abc","def","ghj","xyz"};
            ArrTools.traversal(1,arr);
            ArrTools.traversal(0,arr);
    
            String[] arr1 = ArrUtil.create_Str_Arr(3,5);
            ArrTools.traversal(0,arr1);
    
            int[] arr2 = ArrUtil.create_Int_Arr(4,5);
            ArrTools.traversal(0,arr2);
        }
    
    }
    
    class ArrTools{
    
        /**
         * 该方法用来遍历String类型的数组
         * @param way  该参数用来控制遍历是正序遍历还是逆序遍历:0代表正序遍历,非0代表倒叙遍历
         * @param args 该参数代表传入的参数是String类型的数组
         */
       public static void traversal(int way,String[] args){
           if(way == 0){
               for (int i = 0; i < args.length; i++) {
                   System.out.print((i!=args.length-1)?(i+"=>"+args[i]+'\t'):(i+"=>"+args[i]+'\n'));
               }
           }else{
               for (int i = args.length-1; i >=0 ; i--) {
                   System.out.print((i != 0)?(i+"=>"+args[i]+'\t'):(i+"=>"+args[i]+'\n'));
               }
           }
       }
    
        /**
         * 该方法用来遍历int类型的数组
         * @param way  该参数用来控制遍历是正序遍历还是逆序遍历:0代表正序遍历,非0代表倒叙遍历
         * @param args 该参数代表传入的参数是int类型的数组
         */
        public static void traversal(int way,int[] args){
            if(way == 0){
                for (int i = 0; i < args.length; i++) {
                    System.out.print((i!=args.length-1)?(i+"=>"+args[i]+'\t'):(i+"=>"+args[i]+'\n'));
                }
                return;
            }
            for (int i = args.length-1; i >=0 ; i--) {
                System.out.print((i != 0)?(i+"=>"+args[i]+'\t'):(i+"=>"+args[i]+'\n'));
            }
        }
    
        /**
         * 该方法用来遍历char类型的数组
         * @param way  该参数用来控制遍历是正序遍历还是逆序遍历:0代表正序遍历,非0代表倒叙遍历
         * @param args 该参数代表传入的参数是char类型可变参数,可变参数本质上属于数组
         */
        public static void traversal(int way,char... args){
            if(way == 0){
                for (int i = 0; i < args.length; i++) {
                    System.out.print((i!=args.length-1)?(i+"=>"+args[i]+'\t'):(i+"=>"+args[i]+'\n'));
                }
            }else{
                for (int i = args.length-1; i >=0 ; i--) {
                    System.out.print((i != 0)?(i+"=>"+args[i]+'\t'):(i+"=>"+args[i]+'\n'));
                }
            }
        }
    }
    
    
    class ArrUtil{
    
        /**
         * 该方法用来生成一个String[]类型的数组
         * @param str_len  该参数用来控制每个元素的长度
         * @param arr_size 该参数用来控制数组的长度
         * @return  返回一个String类型的数组
         */
        public static String[] create_Str_Arr(int str_len,int arr_size) {
            String str = "qwertyuioplkjhgfdsamnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM";
            Random  rd = new Random();
            String[] arr = new String[arr_size];
    
            for (int i = 0; i < arr_size; i++) {
                StringBuffer sb = new StringBuffer();
                for (int j = 0; j < str_len; j++) {
                    int index = rd.nextInt(52);
                    sb.append(str.charAt(index));
                }
                arr[i] = sb.toString();
            }
            return arr;
        }
    
        /**
         * 该方法用来生成一个int[]类型的数组
         * @param num_len  该参数用来控制每个元素的长度
         * @param arr_size 该参数用来控制数组的长度
         * @return  返回一个int类型的数组
         */
        public static int[] create_Int_Arr(int num_len,int arr_size) {
            int[] arr = new int[arr_size];
            Random rd = new Random();
            switch (num_len){
                case 1:
                    for (int i = 0; i < arr_size; i++) {
                        arr[i] = rd.nextInt(10);
                    }
                    break;
                case 2:
                    for (int i = 0; i < arr_size; i++) {
                        arr[i] = rd.nextInt(100);
                    }
                    break;
                case 3:
                    for (int i = 0; i < arr_size; i++) {
                        arr[i] = rd.nextInt(1000);
                    }
                    break;
                case 4:
                    for (int i = 0; i < arr_size; i++) {
                        arr[i] = rd.nextInt(10000);
                    }
                    break;
            }
    
            return arr;
        }
    
    }				 
    
    package Test;
    
    /**
     * JVM调用main方法的时候,会自动传递一个String数组过来
     */
    public class ArrayTest03 {
    
        //这个方法程序员负责写出来,JVM负责调用。JVM调用的时候会传递一个String数组
        public static void main(String[] args) {
            //main方法的String数组的长度是0,因为长度为0,所以args不是null
            System.out.println(args.length);
            //main方法的String数组的长度是0,所以访问String数组的第一个元素会发生数组越界异常
            System.out.println(args[0]);
    
            //main方法中传递的String数组args相当于以下的两个数组:args1、agrs2
            String[] args1 = {};
            String[] args2 = new String[0];
            System.out.println("args1的长度:"+args1.length);
            System.out.println("args2的长度:"+args2.length);
    
            /*
                那么main方法中的String数组args什么时候会有值呢?
                    其实这个数组是给用户的,用户可以在控制台上输入参数,这个参数会被自动转换为"String[] agrs"
                    例如在DOS窗口中用一下方式运行程序:
                       java   ArrayTest03 bgp as 100
                       此时JVM会自动将"bgp as 100"通过空格的方式进行分离,分离完之后自动放到"String[] agrs"数组
                       此时"String[] agrs"变为:String[] agrs = {"bgp","as","100"}
                       所以main方法中的"String[] agrs"数组主要是用来接收用户输入参数的。
                    例如在IDEA工具中运行程序:
                        1)方式一:Run右击--->Edit Configurations...--->Application--->ArrayTest03---->Programe arguments
                        2)方式二:ArrayTest03右击---->Edit 'ArrayTest03.main'...---->Programe arguments
             */
    
            /**
             * 以下程序用来说明main方法中的"String[] agrs"数组的作用
             * 模拟一个系统,假设要使用该系统,必须提供用户名和密码登录之后才能使用
             */
            if(args.length != 2){
                System.out.println("使用该系统时需要输入用户名和密码信息,例如:admin 123");
            }
    
            String username = args[0];
            String password = args[1];
            //假设用户名为:admin,密码为:Root@123,其他一律失败
            /*
                //这样编写程序,当传进来的username和password为空时,会发生空指针异常
                if (username.equals("admin") && password.equals("Root@123")){}
                //这样编写程序,可以避免空指针异常的出现,当传进来的username和password为空时,也不会发生空指针异常
                if ("admin".equals(username) && "Root@123".equals(password)){}
             */
            if ("admin".equals(username)&&"Root@123".equals(password)){
                System.out.println("欢迎【"+username+"】使用学生系统");
            }else{
                System.out.println("您输入的用户名或者密码不正确,请重新输入!");
            }
        }
    
    }
    
    package Test;
    
    /**
     * 测试一维数组中存储引用数据类型
     *      一维数组中存储引用数据类型:实际上存储的是java对象的"内存地址",数组中存储的每个元素是"引用"
     */
    public class ArrayTest04 {
        public static void main(String[] args) {
            Animal[] animal_arr = {new Cat(),new Bird()};
            traversal(animal_arr);
        }
    
        public static void traversal(Animal[] animal_arr){
            for (Animal ele : animal_arr) {
                if (ele instanceof Cat){
                    //如果想调用父类中存在的方法不需要向下转型,直接使用父类型的引用调用即可
                    ele.move();
                    //如果想调用子类中特有的方法需要向下转型
                    /*
                    Cat cat= (Cat)ele;
                    cat.catch_Mouse();
                     */
                    //以上两行代码可以合并成如下一行
                    ((Cat) ele).catch_Mouse();
                }else{
                    ele.move();
                    ((Bird)ele).sing();
                }
            }
        }
    }
    
    class Animal{
        public void move(){
            System.out.println("动物在移动");
        }
    }
    
    class Cat extends Animal{
        @Override
        public void move() {
            //super.move();
            System.out.println("猫在走猫步");
        }
    
        public void catch_Mouse(){
            System.out.println("猫抓老鼠!");
        }
    }
    
    class Bird  extends Animal{
        @Override
        public void move() {
            //super.move();
            System.out.println("鸟儿会飞翔");
        }
    
        public void sing(){
            System.out.println("小鸟会唱歌");
        }
    }	
    

    二、一维数组的扩容/缩容
    1、在java语言中,数组一旦创建,其长度不可变,那么数组满了如何解决?
    1)、解决方案:数组满了,需要扩容
    2)、java的数组扩容原理:
    先创建一个大容量数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。
    3)、因为扩容需要拷贝数组,所以说数组扩容的效率很低,所以在开发中提前估计好数组的长度,
    尽可能少的使用数组拷贝,提高效率。
    2、数组拷贝
    源码:
    public static native void arraycopy(Object src, int srcPos,
    Object dest, int destPos,
    int length);

    package Test;
    public class ArrayTest05 {
        public static void main(String[] args) {
            String[] src ={"123a","3rf","rf","rgd","moog"};
            String[] dest = new String[6];
            System.arraycopy(src,0,dest,1,4);
            for (int i = 0; i < dest.length; i++) {
                System.out.print((i!=dest.length-1)?(i+"=>"+dest[i]+'\t'):(i+"=>"+dest[i]+'\n'));
            }
        }
    }
    
    package Test;
    
    public class ArrayTest07 {
        public static void main(String[] args) {
            //"中国"字符串也是java对象,属于String类型
            //Object[] arr ={new Object(),new Student(),"中国"};
    
            MyStack stack = new MyStack();
            for (int i = 0; i <11 ; i++) {
                stack.push(new Product());
            }
            for (int i = 0; i < 11 ; i++) {
                stack.pop();
            }
        }
    }
    
    class Product{
    
    }
    
    class Student{
    
    }
    

    三、二维数组
    1、二维数组其实是一个特殊的一维数组,因为二维数组的每一个元素都是一个一维数组
    2、三维数组是一个特殊的二维数组,因为三维数组的每一个元素都是一个二维数组
    3、二维数组初始化:
    动态初始化:
    数据类型 数组名称[][] = new 数据类型[行的个数][列的个数];
    例如:
    String arr[][] = new String[3][2];
    静态初始化:
    数据类型 数组名称[][] = new 数据类型[][]{{值1,值2…},{值1…},…};
    数据类型 数组名称[][] = {{值1,值2…},{值1…},…};
    int[][] arr = {{1,23,13},{54,15,6},{7,81,90}}
    4、二维数组中元素的"查"和"改"
    数组名称[二维数组中一维数组的下标][一维数组的元素的下标]
    如:
    arr[2][64] 表示第三个一维数组中的第65个元素

    package Test;
    /**
     * 以下程序测试的内容:
     * 1、提供二维数组的正序、倒叙遍历
     * 2、随机生成二维数组
     * 3、数组作为方法的参数
     */		 
    import java.util.Random;
    public class ArrayTest06 {
        public static void main(String[] args) {
    
            //静态初始化二维数组
            int[][] arr1 = {
                    {12,34,45,678,8,4},
                    {4,5,6},
                    {2},
                    {23,43},
                    {498,43,6,54,9}
            };
    
            String[][] arr2 = new String[3][3];
            arr2[0][0] = "西安";
            arr2[1][1] = "南京";
            arr2[2][2] = "成都";
    
            //遍历二维数组
            //正序遍历
            traversal(arr2,0);
    
            //逆序遍历
            traversal(arr2,1);
    
            String[][] arr3 = create_Array(2,5,4);
            traversal(arr3,0);
        }
    
        /**
         * 该方法用来生成一个String[][]类型的二维数组
         * @param row   该参数用来控制二维数组的长度(即行)
         * @param line  该参数用来控制二维数组中一维数组的长度(即列)
         * @param str_len  该参数用来控制二维数组中一维数组的元素的大小(即列的元素的大小)
         * @return  该方法返回值是一个二维数组
         */
        public static String[][] create_Array(int row,int line,int str_len){
            String str = "qwertyuioplkjhgfdsamnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM";
            Random rd = new Random();
            String[][] arr = new String[row][line];
            for (int i = 0; i < row ; i++) {
                for (int j = 0; j < line; j++) {
                    StringBuffer sb = new StringBuffer();
                    for (int m = 0; m < str_len; m++) {
                        int index = rd.nextInt(52);
                        sb.append(str.charAt(index));
                    }
                    arr[i][j] = sb.toString();
                }
            }
            return arr;
        }
    
        /**
         * 该方法用来遍历二维数组
         * @param args 该参数代表传入的实参为一个二维数组
         * @param way  该参数代表传入的实参为一个int类型的数字,用来控制正序遍历和逆序遍历
         */
        public static void traversal(String[][] args,int way){
            if(0 == way){
                for (int i = 0; i < args.length ; i++) {
                    for (int j = 0; j < args[i].length; j++) {
                        System.out.print((j != args[i].length-1)?(args[i][j]+'\t'):(args[i][j]+'\n'));
                    }
                }
                return;
            }else{
                for (int i = args.length-1; i >= 0 ; i--) {
                    for (int j = args[i].length-1; j >=0; j--) {
                        System.out.print((j != 0)?(args[i][j]+'\t'):(args[i][j]+'\n'));
                    }
                }
            }
        }
    }
    
    【模拟栈数据结构练习】			 
    package Test;
    
    import java.util.Arrays;
    
    /**
     * 编写程序:使用一维数组,模拟栈数据结构
     * 要求:
     *  1、这个栈可以存储java中的任何引用数据类型的数据
     *  2、在栈中提供push方法模拟压栈(栈满了,提示信息:压栈失败)
     *  3、在栈中提供pop方法模拟弹栈(栈空了,提示信息:弹栈失败)
     *  4、编写测试程序,new对象,调用push、pop方法来模拟压栈弹栈的动作
     *  5、假设栈的初始化容量是10(注意无参构造方法的编写方式)
     */
    public class MyStack {//栈类
        //提供一个数组来存储栈中的元素
        //为什么使用Object类型的数组?因为这个栈可以存储java中的任何引用数据类型的数组
        Object[] elements;//= new Object[10];
    
        //栈帧,永远指向栈顶元素
        //因为最初的栈是空的,一个元素都没有,所以栈帧的初始值应该为0
        //private int index = 0;//如果index采用0,表示栈帧指向了顶部元素的上方
        //private int index = -1;//如果index采用-1,表示栈帧指向了顶部元素
        private int index;
    
        public MyStack() {
            //动态初始化一个一维数组,默认初始化容量是10
            this.elements = new Object[10];
            //index初始化
            index = -1;
        }
    
        /**
         * 该方法为压栈的方法
         * @param obj 被压入的元素
         */
        public void push(Object obj){
            if(this.index >= this.elements.length-1){
                System.out.println("栈已满,压栈失败");
                return;
            }
            this.index++;
            this.elements[index] = obj;
    
            //以上两句代码可以合成下面一句
            //this.elements[++index] = obj;
            System.out.println("压栈"+obj+"元素成功,栈帧指向:" + index);
        }
    
        /**
         * 该方法为弹栈的方法,从数组中往外取元素,每取出一个元素,栈帧向下移动一位。
         */
        public void pop(){
            if(index < 0){
                System.out.println("弹栈失败,栈已空");
                return;
            }
    
            System.out.print("弹栈"+elements[index]+"元素成功" + index+'\t');
            index--;
            System.out.println("栈帧指向:"+index);
        }
        public Object[] getElements() {
            return elements;
        }
    
        public void setElements(Object[] elements) {
            this.elements = elements;
        }
    
        public int getIndex() {
            return index;
        }
    
        public void setIndex(int index) {
            this.index = index;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            MyStack myStack = (MyStack) o;
            return Arrays.equals(elements, myStack.elements);
        }
    
        @Override
        public int hashCode() {
            return Arrays.hashCode(elements);
        }
    }
    
    展开全文
  • Java数组

    2021-01-08 20:59:33
    二、数组的创建和基本使用 2.1 创建 2.2 使用 2.3 数组的遍历 2.4 数组的默认值 2.5 数组的几种创建方式 2.6 案例 三、数组的扩容 3.1 系统提供的方法 四、值传递和引用传递【重点】 4.1 数组作为参数 ...

    目录

     

    一、数组的概念

    二、数组的创建和基本使用

    2.1 创建

    2.2 使用

    2.3 数组的遍历

    2.4 数组的默认值

    2.5 数组的几种创建方式

    2.6 案例

    三、数组的扩容

    3.1 系统提供的方法

    四、值传递和引用传递【重点】

    4.1 数组作为参数

    4.2 数组作为返回值

    4.3 可变参数

    五、数组的排序

    5.1 冒泡排序

    5.2 选择排序

    5.3 系统提供的排序

    六、二维数组

    案例:杨辉三角


    一、数组的概念

    一组连续的存储空间,存放相同类型的数据。

    连续空间、相同类型、固定大小

    二、数组的创建和基本使用

    2.1 创建

    int [] arr = new int[5]; // 分配5个int类型大小的空间,(5*4个字节)

    数组使用下标访问

    下标从0开始

    例如上面的数组,下标是从0到4,如果下标超过4,会出现下标越界异常

    2.2 使用

    arr[0] = 100; // 赋值
    arr[1] = 20;
    arr[2] = 30;
    arr[3] = 40;
    arr[4] = 50;
    System.out.println(arr[0]); // 取值 100

    2.3 数组的遍历

    // 遍历赋值
    for (int i = 0; i < arr.length; i++) {
        arr[i] += 1; // 数组元素值+1
    }
    ​
    // 遍历取值
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }

    小技巧:arr.length就是数组的长度,在循环中,循环的判断条件不需要手动改变为数字,在创建数组的时候,数组里面有几个值,长度就是几;而且在创建循环使用快捷键的时候,循环会自动将判断条件设置为最近创建的数组。

    2.4 数组的默认值

    int [] arr = new int[5]; // 分配5个int类型大小的空间
    arr[0] = 100; // 赋值
    System.out.println(arr[0]); // 取值 100
    System.out.println(arr[1]); // 取值,默认值,0

    数组元素在没有赋值的情况下,是可以直接取值的,会使用默认值:

    默认值如下:

    整数:0

    小数:0.0

    char:\u0000(Unicode万国码)

    布尔:false

    其他:null(空)

    2.5 数组的几种创建方式

    public class Demo {
        // 数组的几种创建方式
        public static void main(String[] args) {
            // 定义,后赋值
            int n;
            n = 5;
            
            // 定义时赋值
            int m = 5;
    ​
            // 数组定义到赋值过程中有3个步骤:
            // 1.定义
            int [] arr;
            // 2.分配空间
            arr = new int[3];
            // 3.赋值
            arr[0] = 1;
            arr[1] = 2;
            arr[2] = 3;
            
            // 直接在定义的时分配空间,然后赋值
            int [] arr1 = new int[2];
            arr1[0] = 5;
            arr1[1] = 6;
            
            // 定义,分配空间,赋值一次完成
            int [] arr2 = new int[]{2,3,5,8,10}; // 通过元素个数去自动推断空间大小
            // 简写为
            int [] arr3 = {1,2,3,4};
            
            // 1、定义
            int [] arr4;
            // 2、分配空间并赋值
            arr4 = new int[]{2,3,4,5}; // 不能简写为:arr4 = {2,3,4,5};
        }
    }

    2.6 案例

    public class Demo {
        // 给定一个数组,求平均值
        public static void main(String[] args) {
            // 给定数组
            int [] arr = {45,68,79,68,57,33};
            // 先求和,定义一个和值的变量(小数类型)
            int sum = 0;
            // 遍历数组,求和
            for (int i = 0; i < arr.length; i++) {
                sum += arr[i];
            }
            // 求平均值
            double avg = (double)sum / arr.length;
            
            System.out.println("平均值为:" + avg);
        }
    }
    public class Demo2 {
        
        public static void main(String[] args) {
            int index = search(69);
            System.out.println("下标为:" + index);
        }
        
        /**
         * 查找数组中是否存在元素n,如果存在返回相应的下标
         * @param n 数字
         * @return 如果存在返回下标,不存在返回-1
         */
        public static int search(int n) {
            int [] arr = {32,54,67,89,10};
            // 遍历判断元素是否等于n,如果等于,则返回当前元素的下标
            for (int i = 0; i < arr.length; i++) {
                if(arr[i] == n) {
                    return i;
                }
            }
            // 如果没有返回,则返回-1
            return -1;
        }
    }

    三、数组的扩容

    public class Demo5 {
        // 将两个数组相连变成一个新的数组,并显示新数组中的内容
        public static void main(String[] args) {
            // 定义两个数组
            int [] arr1 = {12,54,67,89};
            int [] arr2 = {3,6,19,90};
            // 定义一个能够存储两个数组所有元素的新数组
            int [] bigArr = new int[arr1.length + arr2.length];
            // 将第一个数组的所有元素放入到新数组中,从下标0开始
            for (int i = 0; i < arr1.length; i++) {
                bigArr[i] = arr1[i];
            }
            // 将第二个数组的所有元素放入到新数组中,从下标第一个数组length开始
            for (int i = 0; i < arr2.length; i++) {
                bigArr[arr1.length + i] = arr2[i];
            }
            // 遍历新数组的所有元素
            for (int i = 0; i < bigArr.length; i++) {
                System.out.println(bigArr[i]);
            }
        }   
    }

    数组扩容常见的两种方法,一种是上面说到的手动扩容,另外一种是系统自带的扩容,下面马上介绍

    3.1 系统提供的方法

    常见的方法,系统一般会提供,不用自己去写。

    例如Math类,里面提供了很多数学相关的方法。使用方式通过类名.方法名的方式。例如:求大值:Math.max(23,56);

    系统提供了两个数组复制的方法:System.arraycopy()以及Arrays.copyOf();

    public class Demo1 {
        public static void main(String[] args) {
            // Math类提供了数学相关一些方法处理,包括三角函数等
    //      int max = Math.max(23, 56); // 得到最大值
    //      System.out.println(max);
    //      System.out.println(Math.pow(3, 3)); //求n的m次方
            
            int [] arr1 = {1,2,3,4,5,6}; // 数组1
            int [] arr2 = {11,12,13,14,15,16}; // 数组2
            int [] arr3 = new int[20]; // 数组3
            
            // 5个参数分别为:源数组,源数组复制的起始位置,目标数组,目标数组存储的起始位置,复制的元素个数
            // 使用的特点, 必须先把源数组和目标数组创建好
            System.arraycopy(arr1, 1, arr3, 0, 4);
            System.arraycopy(arr2, 3, arr3, 4, 3);
            
    //      for (int i = 0; i < arr3.length; i++) {
    //          System.out.print(arr3[i]+",");
    //      }
            // 显示数组中的内容
            System.out.println(Arrays.toString(arr3));
            
            int [] arr4 = {1,2,3,4};
            // 数组复制,(可以扩容,也可以缩小)
            int [] arr5 = Arrays.copyOf(arr4, 10);
            System.out.println(Arrays.toString(arr5));
        }
    }

    四、值传递和引用传递【重点】

    值传递,是变量之间赋值时,传递是变量中存的值。

    引用传递,是变量之间赋值时,传递是变量对应的内容的引用(地址)。

    public class Demo2 {
        public static void main(String[] args) {
            // 值传递
            int n = 5; // 在内存中创建一个int类型的变量空间(4字节),并在该空间中存储数值5
            int m = n; // 在内存中创建一个int类型的变量空间,并在该空间中存储变量n所存储的数值,即5
            m = 10; // 将m变量中存储值改变为10
            System.out.println(n); // 5 显示原来的变量n中存储的值,仍然是5
            
            // 引用传递
    //      int [] arr1 = {1,2,3}; // 简化写法
            // 完整写法
            int [] arr1 = new int[3]; // 在内存中创建一个引用(指针)类型的变量空间(32位系统为4字节,64位系统为8字节),然后在内存中分配3个int大小的连续空间(即12个字节),并将该连续空间的首地址存放到引用类型的变量中。
            arr1[0] = 1; // 找到arr1中存放的地址对应的位置,并偏移0(下标)个int大小的空间,存入数值1
            arr1[1] = 2; // 找到arr1中存放的地址对应的位置,并偏移1(下标)个int大小的空间,存入数值2
            arr1[2] = 3; // 找到arr1中存放的地址对应的位置,并偏移2(下标)个int大小的空间,存入数值3
            
            int [] arr2 = arr1; // 在内存中创建一个引用(指针)类型的变量空间,然后将arr1变量中存储的地址存入到该变量空间中。
            arr2[0] = 10; // 找到arr2中存放的地址对应的位置(即arr1中存放的地址对应的位置),并偏移0(下标)个int大小的空间,存入数值10(实际上就是将原来存入1修改为10)
            System.out.println(arr1[0]); // 10 找到arr1中存放的地址对应的位置,并偏移0(下标)个int大小的空间,将该值输出,即为10
        }
    }

    这里有一张图片供大家查看,数组arr1的地址是0x16b4,声明数组arr2,如果让arr2 = arr1 那么arr2的地址直接指向arr1的地址,arr2[0] = 6,如果让arr2[0] = 20,那么arr1[0]也改变成20,因为地址是同一个,其中一个将值改变了,那个其他引用这个地址的数组的值也会相应的改变,这就是引用传递。

    4.1 数组作为参数

    当基本数据类型作为方法参数时,视为值传递,传入后对原来的值没有任何影响。

    数组作为方法参数时,视为引用传递,传入后在方法中对其元素值进行改变对原来的值有影响。

    public class Demo4 {
        public static void main(String[] args) {
            int i = 5;
            int j = 3;
            change(i, j);
            System.out.println("交换后i和j的值为:" + i + "," + j);
            
            int [] arr1 = {3, 5};
            change1(arr1);
            System.out.println("交换后arr1的值为:" + Arrays.toString(arr1));
        }
    ​
        public static void change(int m, int n) {
            System.out.println("交换前m和n的值为:" + m + "," + n);
            m = m ^ n;
            n = m ^ n;
            m = m ^ n;
            System.out.println("交换后m和n的值为:" + m + "," + n);
        }
        
        public static void change1(int [] arr) {
            System.out.println("交换前arr的值为:" + Arrays.toString(arr));
            arr[0] = arr[0] ^ arr[1];
            arr[1] = arr[0] ^ arr[1];
            arr[0] = arr[0] ^ arr[1];
            System.out.println("交换后arr的值为:" + Arrays.toString(arr));
        }
    }
    public class Demo4 {
        public static void main(String[] args) {
            int i = 5;
            int j = 3;
            change(i, j);
            System.out.println("交换后i和j的值为:" + i + "," + j);
            
            int [] arr1 = {3, 5};
            change1(arr1);
            System.out.println("交换后arr1的值为:" + Arrays.toString(arr1));
        }
    ​
        public static void change(int m, int n) {
            System.out.println("交换前m和n的值为:" + m + "," + n);
            m = m ^ n;
            n = m ^ n;
            m = m ^ n;
            System.out.println("交换后m和n的值为:" + m + "," + n);
        }
        
        public static void change1(int [] arr) {
            System.out.println("交换前arr的值为:" + Arrays.toString(arr));
            arr[0] = arr[0] ^ arr[1];
            arr[1] = arr[0] ^ arr[1];
            arr[0] = arr[0] ^ arr[1];
            System.out.println("交换后arr的值为:" + Arrays.toString(arr));
        }
    }

    注意

    容易出错的地方:

    int [] arr1 = {1,2};

    int [] arr2 = arr1;

    arr2 = new int[]{3,4};

    arr1里面的值有没有改变?

    arr1的值不会改变,因为arr2重新存入一个新地址,与arr1完全不相关。

    public class Demo5 {
        // 容易出错的地方
        public static void main(String[] args) {
            // j的值不会改变,因为m重新存入一个新地址,与j完全不相关。
            int [] j = {5};
            m2(j);
            System.out.println("j为:" + Arrays.toString(j));
        }
        
        public static void m2(int [] m) {
            System.out.println("m为:" + Arrays.toString(m));
            m = new int[] {10};
            System.out.println("m为:" + Arrays.toString(m));
        }
    }

    4.2 数组作为返回值

    数组也可以作为方法的返回值。

    一般情况,如果把数组作为参数传入,并在方法中改变该数组的元素,不需要返回值,因为会对原来的数组产生影响。

    注意:但是,如果在方法中创建了新的数组或改变了数组所引用的地址,方法外面是没有影响的,此时就需要将新的数组返回。

    // 数组扩容添加元素:
    public class Demo6 {
        public static void main(String[] args) {
            int [] arr = new int[3];
            arr[0] = 1;
            arr[1] = 2;
            arr[2] = 3;
            arr = add(arr, 4); // 接收返回的新数组
            System.out.println(Arrays.toString(arr));
        }
        
        /**
         * 数组添加元素,将元素n放入到数组
         * @param arr
         * @param n
         */
        public static int[] add(int [] arr, int n) {
            arr = Arrays.copyOf(arr, arr.length + 1); // 创建了新的数组
            arr[arr.length - 1] = n;
    //      System.out.println("扩容并存储了数据后:" + Arrays.toString(arr));
            return arr;
        }
    }

    4.3 可变参数

    语法:在方法的参数中,可以使用变量类型... 来定义一个可变参数,该参数相当于一个数组。

    使用方式:

    在方法中使用时, 当做数组使用。

    在方法外调用该方法时,可以传入多个参数,也可以不传参数,也可以传入数组,比较灵活。

    限制:只能在方法参数中使用,不能单独使用,而且只能在最后一个参数。

    public class Demo7 {
    ​
        public static void main(String[] args) {
            m1(1,2,3,4);
        }
        
        public static void m1(int a, int b, int... n) {
            System.out.println("数组准备打印");
            for (int i = 0; i < n.length; i++) {
                System.out.println(n[i]);
            }
        }
    }

     

    五、数组的排序

    数组的排序是指将数组的元素按照规定的方式来调整位置,形成有序的序列。

    5.1 冒泡排序

    分析:

    每次循环两两比较,如果满足规则就进行交换,会比较n-1次

    比较一轮后会将最大(小)的元素排列到最后,下一轮就可以减少一个比较的元素

    public class Demo1 {
        // 冒泡排序
        public static void main(String[] args) {
            int [] arr = {32, 9, 48, 16, 25, 45, 18};
            for(int i = 0; i < arr.length; i++){
                for(int j = 0; j < arr.length - i - 1; j++){
                    if(arr[j] > arr[j+1]){
                        arr[j] = arr[j] ^ arr[j+1];
                        arr[j+1] = arr[j] ^ arr[j+1];
                        arr[j] = arr[j] ^ arr[j+1];
                    }
                }
            }
            System.out.println(Arrays.toString(arr));
        }
    }

     为了方便大家理解,从网上找了冒泡排序的动图,如有侵权,请联系作者删除

    5.2 选择排序

    分析:

    首先选择第一个元素,作为最小的元素,后面所有的元素依次与此元素进行比较,如果比它小,则进行交换,当循环依次结束后,则选出最小的。

    进一步思考:

    没有必要每次都交换,只需要记住最小元素的下标,循环结束后,让记住的下标所对应的最小元素与当次循环的第一个元素进行交换,此方案只需要交换一次。

    public class Demo2 {
        // 选择排序
        public static void main(String[] args) {
            int [] arr = {32, 18, 48, 16, 25, 45, 9};
            for (int i = 0; i < arr.length; i++) {
                System.out.println("循环前数组为:" + Arrays.toString(arr));
                int index = i;
                for (int j = i+1; j < arr.length; j++) {
                    if(arr[j] < arr[index]) {
                        index = j; 
                    }
                }
                System.out.println("最小的元素下标为" + index);
                if(index != i) {
                    arr[i] = arr[i] ^ arr[index];
                    arr[index] = arr[i] ^ arr[index];
                    arr[i] = arr[i] ^ arr[index];
                }
                System.out.println(Arrays.toString(arr));
            }
        }
    }

     

    5.3 系统提供的排序

    public class Demo3 {
        // 系统提供的排序
        public static void main(String[] args) {
            int [] arr = {32, 18, 48, 16, 25, 45, 9};
            Arrays.sort(arr); // 排序
            System.out.println(Arrays.toString(arr));
        }
    }

    六、二维数组

    二维数组相当于是每一个元素都是数组的一维数组。

    可以理解为一个包含多行多列的表格。

    public class Demo4 {
        // 二维数组
        public static void main(String[] args) {
            int [][] a = new int[3][5]; // 行列都固定
            
            int [][] arr  = new int[3][]; // 行数固定,但是列数不固定
            arr[0] = new int[2];
            arr[1] = new int[3];
            arr[2] = new int[4];
            
            arr[0][0] = 1; // 给第0行0列赋值
            
            // 直接定义时候赋值
            int [][] arr1 = {
                    {1,2},
                    {2,3,4},
                    {3,4,5,6}
            };
            // 取值
            System.out.println(arr1[1][1]);
        }
    }

    案例:杨辉三角

    public class Demo5 {
        // 杨辉三角
        /*
         *     1
         *    1 1
         *   1 2 1
         *  1 3 3 1
         * 1 4 6 4 1 
         * 
         * 1
         * 1 1
         * 1 2 1
         * 1 3 3 1
         * 1 4 6 4 1
         * 1 5 1010 5 1
         */
        public static void main(String[] args) {
            int [][] arr = new int[10][]; // 10行
            for (int i = 0; i < arr.length; i++) {
                arr[i] = new int[i+1]; // 第0行1个元素,第n行n+1个元素
                for (int j = 0; j < arr[i].length; j++) {
                    if(j == 0 || j == arr[i].length - 1) { // 首尾为1
                        arr[i][j] = 1;
                    }else {
                        // 其他的元素等于上一行的元素以及上一行前一个元素之和
                        arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
                    }
                }
            }
            // 输出
            for (int i = 0; i < arr.length; i++) {
                for (int j = 0; j < arr[i].length; j++) {
                    System.out.print(arr[i][j] + "\t");
                }
                System.out.println();
            }
        }
    }

     

    展开全文
  • Java-数组补充

    2021-05-22 18:25:40
    文章目录Java-数组-021 数组声明1.1 静态声明1.2 动态声明2 基本操作2.1 获取数据(查)2.2 设置数据(改)2.3 遍历2.4 常见异常2.4.1 下标越界异常2.4.2 空指针异常2.5 数组传递2.5.1 传值和传引用2.6 数组复制2.6.1 ...
  • Java数组

    2019-07-04 22:21:57
    数组数组引入和定义 int char 数组:是一种数据类型符号为[].这种数据类型可以保存一组数,是一组数的集合。这一组数数据的类型必须是相同的。 数组的定义: 定义变量: int age = 10; 定义数组: int[] ages = ...
  • import java.util.Random; /** * 奖池随机抽奖 */ public class mode2 { public static void main(String[] args) { int[] arr = {888, 588, 10000, 1000, 2}; //奖池 int[] arr1 = new int[arr.length]; //...
  • java06 数组

    2020-01-07 12:18:14
    1.数组的定义和访问 1.1数组的定义 方式一 动态初始化数组的格式: 数据类型[] 数组名称 = new 数据类型[数组长度]; 解析含义: 左侧数据类型:也就是数组当中保存的数据,全都是统一的什么类型 左侧的中括号:...
  • Java数组

    千次阅读 2016-07-21 18:49:56
    java数组 java二位数组
  • 什么是数组?顾名思义,就是数据的组合,把一些相同类型的数放到一组里去。那为什么要用数组呢?...数组可以很好的解决这两个问题,数组名只有一个,只需要使用数组名加下标来访问各个元素的信息即可,遍历的时...
  • Java 反转数组输出

    千次阅读 2021-01-03 00:27:51
    反转数组输出 问题:将数字1,2,3,4,5 反向输出 5,4,3,2,1 前言:对于初学者 最好将代码在编辑器中使用BUG模式跟一下 输入参数:1,2,3,4,5 代码示例 public static void main(String[] args) { //参数 int[] ...
  • JavaBase 数组

    2017-11-24 12:30:00
    数组: 1.在内存中存储一组相同数据类型的集合 2.数组会在内存中开辟一块连续的空间来保存数据 3.数组的长度一旦被定义不能被改变 4.数组下标的最大值是,数组长度-1 数组中的相关概念: 1.定义数组 int...
  • 小王学JAVA数组

    2020-09-24 08:32:45
    (所有笔记来源于哔哩哔哩up遇见狂神说的视频) 数组 什么是数组 数组是相同类型数据的有序集合 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成 每一个数据称作一个数组元素,每个...Java语言使用ne
  • java数组的5种排序方法 文章目录java数组的5种排序方法前言1.冒泡排序2.选择排序3.插入排序4.快速排序5.归并排序后话 前言 java数组的冒泡,选择,插入,快速,归并排序的实现。 1.冒泡排序 实现思路:第一层...
  • java数组是对象1.一个数组是一系列匿名变量,数组就是一些相关变量的集合,数组中的元素可以通过下标来进行访问。类Object中定义的方法都可以用于数组对象。数组元素可以是基本类型也可以是类类型,当然还可以是...
  • Java数组详解

    2019-10-23 18:43:25
    数组使用 数组作为方法的参数及返回值 数组应用 二维数组 数组的定义及初始化 首先,我们要了解什么是数组数组是存放相同类型数据的集合,数组的内存分布是连续的。 我们创建数组一般有三种方式: int[]...
  • 数组的基本概念: 数组指的就是一组相关变量的集合。 ² 声明并开辟数组:数据类型 数组名称[]=new 数据类型[长度]; ² 分布完成: l 声明数组:数据类型 数组名称[] = null; l 开辟数组数组名称 = new ...
  • java数组与Arrays类源码详解

    千次阅读 2019-09-03 10:32:09
    java数组与Arrays类源码详解  java.util.Arrays 类是 JDK 提供的一个工具类,用来处理数组的各种方法,而且每个方法基本上都是静态方法,能直接通过类名Arrays调用。 类的定义 public final class Array { ...
  • 场景描述: 在spring boot中使用sokect 接受来自PHP服务器的执行结果。发送请求后得到的内容中含有乱码,确认了所有编码格式均为UTF-8,并且php端... 网上推荐使用BufferReader读取 但是内置方法不包含按byte[]读...
  • Java 6 数组Array

    2021-03-01 22:55:21
    public class Demo01 { ...// 声明的时候数组并不存在,只有在创建的到时候才存在,而array数组是在栈中,后面开辟的空间10和内容在堆中。 nums = new int[10]; //2.创建数组 这里面可以存放10个int类型
  • java-数组 方法

    2020-11-19 10:02:41
    数组的反转:数组中的元素颠倒顺序,如数组1,2,3,4,5,数组反转后变成5,4,3,2,1. 思路:本质是交换两个变量的值。两种方式 实现反转,就需要将数组的最远端和最近端元素互换。 定义两个变量,保存数组的...
  • 数组 1. 数组的定义和初始化 2. 数组相关的Arrays的源码和应用 未完结
  • java——数组和方法

    2019-10-02 10:34:59
    2)接收用户控制台输入的5个数值,需要将用户输入的5个正整数保存在数组中。每次要求用户输入数 值的提示语句为:“请输入第N个数字,并回车:”(N为次数)。 3)写一静态方法,实现数组升序排序 4)输出结果: 在...
  • java数组

    2019-06-26 21:57:14
    数组时存储数据长度固定的容器,保证多个数据的类型要一致 数组的定义 数组的定义分为三种 2.1第一种叫做动态定义,给与指定长度的数组 格式为:数据类型[] 数组名 = new 数据类型[长度] 比如说要创建int型的大小为12...
  • java08 数组与集合

    2019-04-16 14:31:00
    1 数组的定义与规范一个变量只能存放一个数据,一个数组是一个容器,可以存放多个数据数组的特点1 数组是一种引用数据类型2 数组中的多个数据,类型必须统一3 数组的长度在程序运行期间,不可改变数组的初始化1 动态...
  • Java数组的理解

    2019-10-20 16:31:58
    数组的定义 本质上就是存放相同类型的变量集合。例如: public class test { public static void main(String[] args) { int[] array = {1,2,3,4,5};...那是不是所有类型都可以用数组表示定义呢?...
  • 通过代码把下面的数组里的数字从大到小输出 Intger[] i= {12,31,56,91,9,812,881,31} public static void main(String[] args) { Integer[] integers= {12,31,56,91,9,812,881,31}; int[] ints = Arrays.stream...
  • 为什么用数组 在某些情况下,虽然可以使用单个变量来存储信息,但是如果需要存储的信息较多(例如存储 50 名学生的成绩),这时再依次创建变量声明并赋值就显得非常麻烦。 随着处理的信息量越

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 59,747
精华内容 23,898
关键字:

java用数组接收数字

java 订阅