chap04
目标:数组
----------------------------------------------

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[]
//使用接口声明出的数组
Action[]
//使用数组声明出的数组(也就是二维数组)
int[][]

注意:使用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 = {2,4,6,8};
System.out.println(a2.length);//4

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

/*下面俩种情况是错误的创建方式*/

//编译报错
int[] a3 = 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.ArrayIndexOutOfBoundsException: 4
at com.briup.test.ArrayTest.main(ArrayTest.java:7)

7)数组对象的拷贝
数组对象的长度确定之后便不能修改,但我们可以通过复制数组的内容变通实现改变数组长度。
在java.lang.System类中提供一个名为arraycopy的方法可以实现复制数组中元素的功能

//该方法的声明
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
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引入.
例如:
package com.briup.ch04;

import java.util.Arrays;

public class Xxx{....}

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

例如:
main:
//返回指定元素在数组中的下标位置
//如果找不到则返回一个小于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);
System.out.println(Arrays.toString(a));
//输出结果: [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)(Math.random()*c.length);
int i2 = (int)(Math.random()*c.length);
int i3 = (int)(Math.random()*c.length);
int i4 = (int)(Math.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 Stirng[]{"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
//将来这3个位置上都是要存放一维数组的
int[][] a = new int[3][];

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

2)给二维数组赋值
例如:
int[][] a = new int[3][4];
a[0][0] = 10;
a[0][1] = 10;
a[0][2] = 10;
a[0][3] = 10;

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

a[2][0] = 30;
a[2][1] = 30;
a[2][2] = 30;
a[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.test2(a);
t.test2();
t.test2(1);
t.test2(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
System.out.println();

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

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

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

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

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

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

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

// "#x"表示输出带有十六进制标志的整数。
System.out.printf("%#x", i);//0x4d2
System.out.println();

java_day04_数组的更多相关文章

  1. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  2. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  3. 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)

    建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...

  4. 了解PHP中的Array数组和foreach

    1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组    . 2.例子:一般的数组 这里,我 ...

  5. JavaScript权威指南 - 数组

    JavaScript数组是一种特殊类型的对象. JavaScript数组元素可以为任意类型,最大容纳232-1个元素. JavaScript数组是动态的,有新元素添加时,自动更新length属性. J ...

  6. JavaScript常见的五种数组去重的方式

    ▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...

  7. js:给定两个数组,如何判断他们的相对应下标的元素类型是一样的

    题目: 给Array对象原型上添加一个sameStructureAs方法,该方法接收一个任意类型的参数,要求返回当前数组与传入参数数组(假定是)相对应下标的元素类型是否一致. 假设已经写好了Array ...

  8. javascript数组查重方法总结

    文章参考地址:http://blog.csdn.net/chengxuyuan20100425/article/details/8497277 题目 对下列数组去重: var arr = ['aa', ...

  9. 掌握javascript中的最基础数据结构-----数组

    这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...

随机推荐

  1. Selenium 2自动化测试实战35(HTML测试报告)

    HTML测试报告 显然,一份漂亮的测试报告展示自动化测试成果只有一个简单的log文件是不够的.HTMLTestRunner是python标准库unittest单元测试框架的一个扩展,它生成易于使用的H ...

  2. 利用beautifulsoup下载网页html代码中的css, js, img文件并保存

    # -*- coding:utf-8 -*- from bs4 import BeautifulSoup as BS import urllib.request as rqst import os u ...

  3. 在java中有关于反射的皮毛----自己的简略认知

    白首为功名.旧山松竹老,阻归程.欲将心事付瑶琴.知音少,弦断有谁听? 反射(reflection): 当我们在看到这个名词首先会想到的是,我们在上高中时学的物理,那么在java开发中,反射这个名词是怎 ...

  4. SQL SERVER CLR Trigger功能

    通过在 Microsoft SQL Server 中托管 CLR(称为 CLR 集成),开发人员可以在托管代码中编写存储过程.触发器.用户定义函数.用户定义类型和用户定义聚合函数, 改变了以前只能通过 ...

  5. Python 线程----线程方法,线程事件,线程队列,线程池,GIL锁,协程,Greenlet

    主要内容: 线程的一些其他方法 线程事件 线程队列 线程池 GIL锁 协程 Greenlet Gevent 一. 线程(threading)的一些其他方法 from threading import ...

  6. fdisk中参数配置说明表

    命令 描述 a 设置活动分区标志 b 编辑BSD Unix系统用的磁盘标签 c 设置DOS兼容标志 d 删除分区 l 显示可用的分区类型 m 显示命令选项(帮助) n 添加一个新的分区 o 创建DOS ...

  7. USACO 1.1 Greedy Gift Givers

    模拟. 如果用$map$的话,会很好写. 如果你不会$map$的话,在此小广告:https://blog.csdn.net/CQBZLYTina/article/details/80063739 /* ...

  8. 通过火狐谋智查询API

    谋智中文版网址 https://developer.mozilla.org 示例 site: developer.mozilla.org window 通过百度高级用法查API site: 网址 搜索 ...

  9. android带参和不带参的页面跳转形式

    FActivity.java package com.example.demo06; import android.app.Activity;import android.content.Contex ...

  10. Infix to Prefix conversion using two stacks

    Infix : An expression is called the Infix expression if the operator appears in between the operands ...