corejava_day4

目标:数组


数组

1. 概述

数组是一组数据的集合,数组中的每个数据被称为元素。在Java中,数组也是对象。数组中的元素可以是任意类型(基本类型和引用类),但同一个数组里只能存放类型相同的元素。

数组类型的变量、类类型的变量、接口类型的变量都属于引用类型的变量,这些变量都是可以指向其相应的对象的,那么数组类型的变量指向的就是数组对象。

接触第一个数组类型变量,就是main方法的参数

public static void main(String[] args) {
    
}

其中String[]就是一个数组类型,args就是这个数据类型的变量,它所指向的数组对象中只能存放String类型的数据。

注:main方法是由JVM负责调用,那么args所指向的数组对象也是由JVM负责创建并传过来。


2. 声明数组类型变量

1. 数组类型

8种基本数据类型和3种引用类型,使用这些都可以声明出数组类型

任意类型都可以声明成数组类型,只需要加 “[]” 即可。

例如:

基本类型的数组:

byte[] short[] int[] long[] float[] double[] char[] boolean[]

引用类型的数组:

// 使用类声明出的数组
Student[] 
// 使用数组声明出的数组(也就是二维数组)
int[][]
// 使用接口声明出的数组
Action[]

注意:使用X类型声明出的数组,那么将来该数组中就只能存放X类型的数据

2. 数组类型变量

有两种形式可以声明数组变量,推荐使用第一种。

int[] a;
或者
int a[];

String[] str;
Student[] students;
long[] l;

注:数组类型变量将来是要指向对象的。


3. 创建数组对象

1. 数组对象的长度

数组的长度是指一个数组对象中可以存放多个数据(元素)。

每一个数组对象在被创建的时候,就需要指明其长度是多少,并且该长度一定确定就不能再做修改。

2. 数组对象的创建

创建数组对象使用new关键字即可。

例如:

int[] a = new int[4];
String[] str = new String[1];
// 表示该数组对象中一个数据都存放不了
char[] c = new char[0];
// 编译报错,因为创建数组对象的时候不知道其长度
long[] v = new long[];

3. 获得数组对象的长度

使用数组对象访问其length属性即可获得该数组的长度

例如:

int[] a = new int[4];
System.out.println(a.length); // 4

注意:对象创建后,数组的长度是不能改变的。

例如:

// 编译报错
int[] a = new int[4];
a.length = 8;

// 编译通过
// 但是这只是又新建了一个数组对象
// 而不是改变原来数组对象的长度
int[] a = new int[4];
a = new int[8];

4. 数组对象的初始化及使用

1. 数组对象在内存中的位置

数组对象也是Java中的一种对象,但是和之前使用类创建出的对象还是一定区别的。

数组对象也存放在内存中的堆区,并且数组对象在堆区中是一块连续的内存空间,这其中的每一小块空间都可以存放我们要保存的一个数组(元素)。那么数组的长度指的其实也就是这个东西。

注:数据对象其实就是堆区中的一块连续的内存空间。

2. 数组对象中每个元素位置上的默认值

数组对象中的默认值和要保存的数据类型有关

例如:

int[] a = new int[4];
整型数组的默认值是      0
浮点型数组的默认值是    0.0
布尔类型数组的默认值是  false
字符类型数组的默认值是  0
引用类型数组的默认值是  null

3. 数组对象中的元素位置的下标

由于数组对象在堆区中是一块连续的内存空间,那么我们可以通过连续的下标,找到每一个可以存放数据的元素位置。

注:下标是从0开始的

例如:

// 通过下标0 1 2 3可以访问到数组对象中四个元素位置的值
// 整型的默认值是 0 
int[] a = new int[4];
System.out.println(a[0]); // 0
System.out.println(a[1]); // 0
System.out.println(a[2]); // 0
System.out.println(a[3]); // 0

// 布尔的默认值是 false
boolean[] a = new boolean[4];
System.out.println(a[0]); // false
System.out.println(a[1]); // false
System.out.println(a[2]); // false
System.out.println(a[3]); // false

总结:如果一个数组对象的长度是n,那么这个数组下标的值是[0,n-1],其实n必须大于0

4. 使用数组的下标赋值

String[] str = new String[3];
// 赋值前:使用循环输出数组中的元素
for(int i=0;i<str.length;i++) {
    System.out.println(str[i]);
}
str[0] = "hello";
str[1] = "world";
str[2] = "test";

// 赋值后:使用循环输出数组中的元素
for(int i=0;i<str.length;i++) {
    System.out.println(str[i]);
}

5. 特殊形式

// 编译通过
int[] a1 = new int[] {1,3,5,7,9};
System.out.println(a1.length); // 5

// 编译通过
int[] a2 = new {2,4,6,8};
System.out.println(a2.length); // 4

// 编译通过
int[] a3;
a3 = new int[] {1,2,3};
System.out.println(a3.length); // 3

// 编译报错
int[] a4 = new int[3]{1,2,3};

// 编译报错
int[] a4;
a4 = {1,2,3};

6. 数组下标越界

对于一个长度为n的数组对象,它的下标取值范围是[0,n-1],这里的0和n-1就是这个数组对象的下标边界,使用下标的过程中不能超出这个边界。如果超出那么就会运行报错。

例如:

int[] a = new int[4];
a[4] = 10;

运行后结果:
Exception in thread “main” java.lang.ArrayIndexOutBoundsException

7. 数组对象的拷贝

数组对象的长度确定之后便不能修改,但我们可以通过复制数组的内容改变数组长度。

在java.lang.System类中提供一个名为arraycopy的方法可以实现复制数组中元素的功能

// 该方法的声明
public static void arraycopy(Object src,int srcPos,Object dest,int desPos,int length)
参数1,需要被复制的目标数组
参数2,从这个数组的那个一个位置开始复制
参数3,需要把数据复制到的另外的那一个新的数组对象
参数4,复制到新数组里面哪个位置(从这个位置开始算)
参数5,复制的目标数组的长度

例如:

写一个方法,接收一个数组对象,把这个数组对象的长度扩大到原来的2倍并返回。

public int[] test(int[] a) {
    int[] b = new int[a.length*2];
    System.arraycopy(a,0,b,0,a.length);
    return b;
}

8. 数组的工具类java.util.Arrays

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

1. Arrays类的引入

该是java.util包中的类,在我们的代码中想使用这个类的话,就必须使用import进行导入。

在当前类A中,只有java.lang包下的类,以及和当前类A在同一个包下的类,不需要import引入之外,其他所有的包下的类在被使用之前都要import引入。

例如:

import java.util.Arrays;

public class Xxx(){...}
2. Arrays类中方法的调用

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

例如:

// 返回指定元素在数组中的下标位置
// 如果找不到则返回一个小于0的数
int[] a = {1,3,5,7,9};
int key = Arrays.binarySearch(a,7);
System.out.println(key); // 3
3. Arrays类中常用方法
  • toString方法,把数组转换为字符串形式并返回

例如:

int[] a = {1,3,5,7,9};
System.out.println(Arrays.toString(a);
// 输出结果:[1,3,5,7,9]
  • binarySearch方法,在数组中查找指定元素并返回其下标

例如:

int[] a = {1,3,5,7,9};
int key = Arrays.binarySearch(a,7);
System.out.println(key); // 3

注:使用二分搜索法来搜索指定的数组,以获得指定的值。必须在进行此调用之前对数组进行排序(通过sort方法等)。如果没有对数组进行排序,则结果是不确定的。如果数组包含多个带有指定值的元素,则无法保证找到的是哪一个

  • copyOf方法,复制或者截取指定数组并返回

例如:复制

int[] a = {1,3,5,7,9};
a = Arrays.copyOf(a,8);
System.out.println(Arrays.toString(a));
// 输出结果:[1,3,5,7,9,0,0,0]

例如:截取

int[] a = {1,3,5,7,9};
a = Arrays.copyOf(a,2);
System.out.println(Arrays.toString(a));
// 输出结果:[1,3]
  • copyOfRange方法,将数组中指定范围复制新数组并返回

例如:

int[] a = {1,3,5,7,9};
a = Arrays.copyOfRange(a,1,3);
// 输出结果:[3,5]
  • equals方法,比较两个数组是否相等

例如:

int[] a = {1,3,5,7,9};
int[] b = {1,3,5,7,9};

System.out.println(Arrays.equals(a,b)); // true
System.out.println(a == b); // false

注意:==比较的是引用所指向对象的内存地址

Arrays.equals方法比较是两个数组中的内容

  • fill方法,用指定值去填充数组对象

例如:

int[] a = {1,3,5,7,9};
Arrays.fill(a,99);
System.out.println(Arrays.toString(a));
// 输出结果:[99,99,99,99,99]
  • sort方法,把数据中的元素进行排序

例如:

int[] a = {3,5,1,9,7};
System.out.println("before:\t" + Arrays.toString(a));
Arrays.sort(a);
System.out.println("after:\t" + Arrays.toString(a));
// 输出结果:
before:[3,5,1,9,7]
after:[1,3,5,7,9]
  • asList方法,可以把数组转换为List集合。

5. 数组使用例子

1. 求一组值的平均值

public double getAvg(int[] a) {
    double sum = 0;
    for(int i=0;i>a.length;i++) {
        sum += a[i];
    }
    return sum/a.length;
}

2. 求一组的最大值

public int getMax(int[] a){
    int max = a[0];
    for(int i=1;i<a.length;i++) {
        if(a[i] > max) {
            max = a[i];
        }
    }
    return max;
}

3. 冒泡排序

相邻的两个元素比较,让值较大的数据逐渐向数组的底部(即朝最后一个元素)移动。

public void sort(int[] a) {
    for(int i=0;i<a.length-1;i++) {
        for(int j=0;j<a.length-i-1;j++) {
            if(a[j]>a[j+1]) {
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
            }
        }
    }
}

4. 从众多手机号码中抽取一个获奖手机号码

public String getTel(String[] str) {
    int index = (int)(Math.random()*n.length);
    return str[index];
}

注意:Math.random()返回值是[0,1)之间的double类型的随机数

5. 产生四位长度的验证码,验证码内容为大小写字母或数字组成

public String getValidateCode() {
    String s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    char[] c = s.toCharArray();
    int i1 = (int)(March.random()*c.length);
    int i2 = (int)(March.random()*c.length);
    int i3 = (int)(March.random()*c.length);
    int i4 = (int)(March.random()*c.length);
    
    return ""+c[i1]+c[i2]+c[i3]+c[i4];
}

6. 二维数组

既然任何类型都可以声明为数组,那么给数组再加一个[]就得到了二维数组,类似的二维数组再加一个[]就得到三维数组。

假定某个宾馆有三层楼,第一层有4个房间,第二层有3个房间,第三层有5个房间。某一天客户入住情况如下所示:

第三层: |      | Tom  | Jerry |     | Rose| 
第二层: | Mary |      | Kevin | 
第一层: | Mike | Jane | Duke  |     |

可以用两维数组来存储各个房间的客人信息。

String[][] room = new String[3][];
room[0] = new String[] {"Mike","Jane","Duke",null};
room[1] = new String[] {"Mary",null,"Kevin"};
room[2] = new String[] {null,"Tom","Jerry",null,"Rose"};

1. 声明并创建二维数组

// 堆区有一块连续的内存空间,里面有3个元素位置
// 每个元素位置中都存放了一个一维数组
// 每个一维数组中都有4个元素位置
// 这个4个元素位置上的值都默认是0
int[][] a = new int[3][4];

// 堆区有一块连续的内存空间,里面有3个元素位置
// 每个元素位置上都只有默认值null
// 将来这个三个位置上都是要存放一维数组的
int[][] a = new int[3][];

// 编译报错
int[][] a = new int[][];

2. 给二维数组赋值

例如:

int[][] a = new int[3][4];
int[0][0] = 10;
int[0][1] = 10;
int[0][2] = 10;
int[0][3] = 10;

int[1][0] = 20;
int[1][1] = 20;
int[1][2] = 20;
int[1][3] = 20;

int[2][0] = 30;
int[2][1] = 30;
int[2][2] = 30;
int[2][3] = 30;

int[][] a = new int[3][];
a[0] = new int[1];
a[1] = new int[2];
a[2] = new int[3];

a[0][0] = 10;

a[1][0] = 20;
a[1][1] = 20;

a[2][0] = 30;
a[2][1] = 30;
a[2][2] = 30;

3. 特殊情况

// 编译通过
int[][] a = {
    {1},
    {1,2},
    {1,2,3}
};

// 编译通过
int[][] a4 = new int[][] {
    {1},{1,2},{1,2,3}
};

// 编译报错
int[][] a5 = new int[3][] {
    {1},{1,2},{1,2,3}
};

4. 二维数组结合循环

String[][] str = {
    {"test1"},
    {"hello1","hello2"},
    {"world1","world2","world3"}
};

// 循环三次,因为str中有三个元素
// 只不过这三个元素每一个都是一维数组
for(int i=0;i<str.length;i++) {
    // 第一个一维数组中有1个元素,元素是String类型的
    // 第二个一维数组中有2个元素,元素是String类型的
    // 第三个一维数组中有3个元素,元素是String类型的
    for(int j=0;j<str[i].length;j++) {
        System.out.println(str[i][j]);
    }
}

7. 可变参数

注:只有在JDK1.5或以上版本中可用

例如:

public void test(int[] a) {
    
}

// 调用这个方法的时候,“只能”传入一个int[]类型的参数
int[] a ={1,2,3};
t.test(a);

// 但是如果使用可变参数:
public void test(int...a) {
    
}

// 那么调用的时候传入的参数类型及形式就会比较多样
int[] a = {1,2,3,4};
t.test(a);
t.test();
t.test(1);
t.test(1,2,3,4,5,6,7);

// 可变参数前面可以加其他参数,但可变参数后面再加其他参数就会报错
public void test(String msg,int... a) {
    
}
// 调用方法:
int[] a = {1,2,3,4};
String msg = "hello";
t.test(msg,a);
t.test(msg);
t.test(msg,1);
t.test(msg,1,2,3,4,5,6,7);

注:在方法内部,这个可变参数我们使用的时候直接把它当做数组就可以了

public void test(int... a) {
    System.out.println(a.length);
}

8. 格式化输出(了解)

注:只有在JDK1.5或以上版本可用

// 定义一些变量,用来格式化输出
double d = 345.678;
int i = 1234;

// "%"表示进行格式化输出,"%"之后的内容为格式的定义。
// "f"表示格式化输出浮点数。
System.out.printf("%f",d); // 345.678000

// "9.2"中的9表示输出的长度,2表示小数点后的位数。注意输出数字前面的空格也是算在长度里的
System.out.printf("%9.2f",d); // 345.68

// "+"表示输出的数带正符号
System.out.printf("%+9.2f",d); // +345.68

// "-"表示输出的数左对齐(默认为右对齐)
System.out.printf("%-9.4f", d); // 345.6780


//"+-"表示输出的数带正符号且且左对齐
System.out.printf("%+-9.3f", d); // +345.678

// "d"表示输出十进制整数
System.out.printf("%d", i); // 1234

// "o"表示输出八进制整数
System.out.printf("%o", i); // 2322

// "x"表示输出十六进制整数
System.out.printf("%x", i); // 4d2

// "#x"表示输出带有十六进制标志的整数
System.out.printf("%#x", i); // 0x4d2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值