数组的定义及使用
数组是一组相关数据的集合,一个数组实际上就是一连串的变量,数组按照使用可以分为一维数组、二维数组、多维数组;
一维数组
要使用java的数组,必须经过连个步骤:1、声明数组2、为该数组分配内存
* 声明形式一:
声明一维数组:数据类型 数组名[ ]=null;
分配内存给该数组:数组名 =new 数据类型[长度];
* 声明形式二:
声明一维数组(数组的静态初始化):数据类型 数组名[ ]={变量1,变量2,变量3……};
public class ArrayDemo01
{
public static void main(String args[]){
int score[]=null; //声明数组
score=new int[5]; //为数组开辟空间,大小为3
System.out.println(score.length);
//可以采用数组名[下标]来进行访问
System.out.println("score[0] "+score[0]);
System.out.println("score[1] "+score[1]);
System.out.println("score[2] "+score[2]);
System.out.println("score[3] "+score[3]);
//也可以使用for循环来进行访问,得到的效果是一样的
for(int i=0;i<score.length;i++){
System.out.println("score["+i+"] "+score[i]);
}
}
}
数组的下标是从0开始的,通过score.length(数组的属性)可以获得当前数组的长度
访问注意:
因为数组的下标是从0开始的,如果索引超出下标的范围,则会抛出java.lang.ArrayIndexOutOfBoundsException 数组索引越界异常
范例一:判断一组数组中的最大值
public class ArrayDemo02
{
public static void main(String args[]){
int score[]={12,43,1,54,23,89}; //使用静态初始化为数组赋值
int max=0; //保存数组中的最大值
int min=0; //保存数组中的最小值
max = min =score[0]; //把数组中的第一个元素赋给max和min 目的是为了取得数组中的最小值 而不是自定义的0
for(int i=0;i<score.length;i++){ //循环输出
if(score[i]>max){ //依次判断后续元素是否比max大
max=score[i]; //如果大,则赋值给max
}
if(score[i]<min) //依次判断后续元素是否比min小
min=score[i]; //如果小,则赋值给min
}
System.out.println("数组中的最大值为:"+max);
System.out.println("数组中的最小值为:"+min);
}
}
冒泡排序法:从小到大排列数组中的元素:
public class ArrayDemo03
{
public static void main(String args[]){
int score[]={12,43,1,54,23,89}; //使用静态初始化为数组赋值
int temp=0;
for(int i=0;i<score.length;i++){
for(int j=0;j<score.length;j++){
if(score[j]>score[i]){
temp=score[i];
score[i]=score[j];
score[j]=temp;
}
}
}
for(int k=0;k<score.length;k++){
System.out.println(score[k]);
}
}
}
二维数组
二维数组的声明方式和一维数组的类似,内存的分配也一样是用new 关键字。其声明与分配内存的格式如下:
·动态初始化:
1、 数据类型 数组名[ ] [ ]=null;
2、 数组名 =new 数据类型[行的个数][列的个数];
·静态初始化:
数据类型 数组名[] [ ]={{第0行初始值},{第1行初始值},….{第n行初始值}};
二维数组是数组的数组,若要想取得一个二维数组的长度,则要使用 数组名.length,实际上就是数组的行数;若要取得当前数组当前行列的个数,则用 数组名[行的个数].length
二维数组的输出要采用嵌套for循环的方式:代码如下
public class ArrayDemo04
{
public static void main(String args[]){
int score[][]=new int[3][3]; //动态初始化二维数组
score[1][0]=30; //为二维数组中第2行第1列赋值
score[0][1]=30; //为二维数组中第1行第2列赋值
score[2][0]=30; //为二维数组中第3行第1列赋值
score[1][1]=30; //为二维数组中第2行第2列赋值
System.out.println("当前数组的行数为:"+score.length);
System.out.println("当前数组的第1列的长度为:"+score[1].length);
for(int i=0;i<score.length;i++){ //外层循环行score.length为数组行数
for(int j=0;j<score[i].length;j++){ //内层循环列 score[i].length为数组的列数
System.out.print(score[i][j]+"\t");
}
System.out.println(""); //换行
}
}
}
二维数组的静态初始化:
public class ArrayDemo05{
public static void main(String args[]){
int score[][] = {
{67,61},{78,89,83},{99,100,98,66,95}
} ; // 静态初始化完成,每行的数组元素个数不一样1
for(int i=0;i<score.length;i++){
for(int j=0;j<score[i].length;j++){
System.out.print(score[i][j] + "\t") ;
}
System.out.println("") ;
}
}
};
多维数组
经过前面的一维和二维我们已经发现,想要提高数组的维数,只要在声明数组的时候将索引与括号再加一组即可,所以三维数组的声明方式为:score[ ][ ][ ];四维数组的声明方式为:score[ ] [ ] [ ] [ ],以此类推。
三维数组的声明及输出代码如下:
public class ArrayDemo10{
public static void main(String args[]){
int score[][][] = {
{
{5,1} ,{6,7}
},
{
{9,4},{8,3}
}
} ; // 静态初始化完成,每行的数组元素个数不一样1
for(int i=0;i<score.length;i++){
for(int j=0;j<score[i].length;j++){
for(int k=0;k<score[i][j].length;k++)
{
System.out.println("score["+i+"]["+j+"]["+k+"] = "+score[i][j][k] + "\t") ;
}
}
}
}
};
开发中很少使用多维数组的,一般是使用一维数组或者是二维数组已经足够。只需了解即可。
方法的声明及使用
方法:方法就是一段可以重复调用的代码段。
1、 没有返回值类型,没有参数:修饰符 void 方法名(){方法体};
2、 没有返回值类型,有参数:修饰符 void 方法名(参数类型 参数名){方法体};
3、 有返回值类型,没有参数:修饰符 返回类型 方法名(){方法体};
4、 有返回值类型,有参数:修饰符 返回类型 方法名(参数类型 参数名){方法体};
5、 静态的方法:在修饰符后面添加static即可。
使用static 声明的方法,可以直接 类名称.方法名,没有声明的则进行类的实例化
在main方法中直接调用本类中的静态方法:
public class MethodDemo01{
public static void main(String args[]){
printInfo() ; // 调用printInfo()方法
printInfo() ; // 调用printInfo()方法
printInfo() ; // 调用printInfo()方法
System.out.println("Hello World!!!") ;
}
public static void printInfo(){
char c[] = {'H','e','l','l',
'o',',','L','X','H'} ; // 定义字符数组
for(int x=0;x<c.length;x++){ // 循环输出
System.out.print(c[x]) ;
}
System.out.println("") ; // 换行
}
};
调用有返回值类型的方法:
public class MethoDemo02{
public static void main(String args[]){
int one = addOne(10,20) ; // 调用整型的加法操作
float two = addTwo(10.3f,13.3f) ; // 调用浮点数的加法操作
System.out.println("addOne的计算结果:" + one) ;
System.out.println("addTwo的计算结果:" + two) ;
}
// 定义方法,完成两个数字的相加操作,方法返回一个int型数据
public static int addOne(int x,int y){
int temp = 0 ; // 方法中的参数,是局部变量
temp = x + y ; // 执行加法计算
return temp ; // 返回计算结果
}
// 定义方法,完成两个数字的相加操作,方法的返回值是一个float型数据
public static float addTwo(float x,float y){
float temp = 0 ; // 方法中的参数,是局部变量
temp = x + y ; // 执行加法操作
return temp ; // 返回计算结果
}
};
方法的重载
方法的重载就是方法名称相同,但参数的类型和参数的个数不同,通过传递参数的个数及类型不同以完成不同功能的方法调用。
方法重载的具体实现代码如下:
public class MethoDemo03{
public static void main(String args[]){
int one = add(10,20) ; // 调用整型的加法操作
float two = add(10.3f,13.3f) ; // 调用浮点数的加法操作
int three = add(10,20,30) ; // 调用有三个参数的加法操作
System.out.println("add(int x,int y)的计算结果:" + one) ;
System.out.println("add(float x,float y)的计算结果:" + two) ;
System.out.println("(int x,int y,int z)的计算结果:" + three) ;
}
// 定义方法,完成两个数字的相加操作,方法返回一个int型数据
public static int add(int x,int y){
int temp = 0 ; // 方法中的参数,是局部变量
temp = x + y ; // 执行加法计算
return temp ; // 返回计算结果
}
public static int add(int x,int y,int z){
int temp = 0 ; // 方法中的参数,是局部变量
temp = x + y + z ; // 执行加法计算
return temp ; // 返回计算结果
}
// 定义方法,完成两个数字的相加操作,方法的返回值是一个float型数据
public static float add(float x,float y){
float temp = 0 ; // 方法中的参数,是局部变量
temp = x + y ; // 执行加法操作
return temp ; // 返回计算结果
}
};
提示:System.out.println();本身也是属于方法的重载;方法的重载的注意事项:一定只是在参数的类型或个数不同
补充:在java面试中经常会遇到方法的重写与重载的不同
方法的重写:类继承父类,并在子类中定义一个与父类中的方法名称和参数都相同的方法(返回类型可以不同) 就会覆盖父类中的方法,叫做方法的重写。并且重写只有在具有继承关系的类中出现
使用return结束一个方法
return 可以返回一个方法的结果,在java中也可以使用return结束一个方法
public class MethoDemo05{
public static void main(String args[]){
System.out.println("1、调用fun()方法之前。") ;
fun(10) ;
System.out.println("2、调用fun()方法之后。") ;
}
public static void fun(int x){
System.out.println("3、进入fun()方法。") ;
if(x==10){
return ; // 结束方法,返回被调用处
}
System.out.println("4、正常执行完fun()方法。") ;
}
};
以上程序中(“正常执行完fun()方法”)不会执行。return 已将方法结束
方法的递归调用
递归调用是一种特殊的调用形式,是方法自己调用自己。
下面采用方法的递归完成数字的累加功能:
public class MethodDemo01
{
public static void main(String args[])
{
System.out.println("计算结果:"+sum(100));
}
public static int sum(int num){ //定义累加的方法
if(num==1){
return 1; //判断是否加到了最后一个数
}
else{
return num+sum(num-1); //递归调用
}
}
}
注意事项:在使用方法的递归调用时,一定要写出方法结束的条件,否则会出现操作内存溢出。
方法的递推
递推就是利用循环迭达的方法一步一步进行计算,知道达到目的,它是属于数学中的的函数,也叫做递推数列
递归与递推的比较:
递归要进行函数的调用,是在于压栈和出栈的操作 这是主要的开销,但是递推就不用函数的栈操作 只是运用数学上的函数,所以两者运行起来的话,递推的方式 效率和性能比较高一些,但是有些功能递推是实现不了的。
下面是常用的递归和递推的例子:(来源网络)
最好的例子是斐波那契数列: 1 1 2 3 5 8 13 21 ... ...
总结成公式就是F(n+1)=F(n)+F(n-1), F(0)=F(1)=1;
你可以用递归的方法写这个函数:
int F(int n) {
if (n <2) return 1;
else return F(n-1)+F(n-2);
}
但也可以用递推的方式:
int F(int n) {
if (n <2) return 1;
int f0=1, f1=1, f;
for (int i=0; i <n-1; i++) {
f=f0+f1;
f1=f; f0=f1;
}
}
显然能用递推的话就用递推, 一般肯定要比递归快,除非有的问题不用递归做不出来的.
线性规划法在推导时往往是用递归的形式,但最后可以化为递推
数组的引用传递
一个方法可以接收一个数组,也可以返回一个数组,如果一个方法接收一个数组的话,则此方法对数组的修改最终都会被保留下来
public class ArrayRefDemo01
{
public static void main(String args[]){
String[] demo={"1","2","3"}; //静态初始化数组
fun(demo);
for(int i=0;i<demo.length;i++){ //循环输出
System.out.println(demo[i]);
}
}
public static void fun(String[] str){
str[0]="10"; //修改数组中第一个元素
}
}
方法除了可以接收数组之外,也可以通过方法返回一个数组,只需要在返回值类型上,明确的说明返回类型是数组即可。代码如下:
public class ArrayRefDemo02
{
public static void main(String args[]){
String demo[]=fun();
print(demo);
}
public static void print(String str[]){
for(int i=0;i<str.length;i++){ //循环输出
System.out.println(str[i]);
}
}
public static String[] fun(){
String str[]={"1","2","3"};
return str;
}
}
Java对数组排序的支持:java.util.Arrays.sort(数组名);
public class ArrayRefDemo03
{
public static void main(String args[]){
int demo[]={12,32,1,3,54}; //静态初始化数组
java.util.Arrays.sort(demo); //使用java中Arrays.sort()方法对数组进行排序(小大)
print(demo); //输出数组中的元素
}
public static void print(int str[]){ //定义输出数组中元素的方法
for(int i=0;i<str.length;i++){ //循环输出
System.out.println(str[i]);
}
}
}
数组拷贝
可以将一个数组的内容拷贝到另外一个数组,如果要实现这种设计,则应该传递的参数为:
1、 源数组 2、源数组的开始点 3、目标数组 4、目标数组的开始点 5、拷贝的长度
实现代码如下:
public class ArrayRefDemo04
{
public static void main(String args[]){
int a[]={1,2,3,4,5,6,7,8,9};
int b[]={11,22,33,44,55,66,77,88,99};
copy(a,1,b,1,3); //将b中22,33,44替换为2,3,4
print(b);
}
//源数组、源数组的开始点、目标数组、目标数组的开始点、拷贝的长度
public static void copy(int s[],int si,int o[],int oi,int len){
for(int i=0;i<len;i++){
o[oi+i]=s[si+i];
}
}
public static void print(int str[]){ //定义输出数组中元素的方法
for(int i=0;i<str.length;i++){ //循环输出
System.out.println(str[i]);
}
}
}
此种数组的拷贝java也是支持的,采用的是System.arraycopy(源数组(数组名),源数组的开始点(int),目标数组(数组名),目标数组的开始点(int),拷贝的长度(int));具体如下:
public class ArrayRefDemo05
{
public static void main(String args[]){
int a[]={1,2,3,4,5,6,7,8,9};
int b[]={11,22,33,44,55,66,77,88,99};
System.arraycopy(a,1,b,1,3); //将b中22,33,44替换为2,3,4
print(b);
}
public static void print(int str[]){ //定义输出数组中元素的方法
for(int i=0;i<str.length;i++){ //循环输出
System.out.println(str[i]);
}
}
}
Java新特性对数组的支持
可变参数
在调用一个方法的时候,必须根据方法的定义传递指定的参数,但是在JDK1.5之后产生了新的概念—可变参数,即:方法中接收的参数不再是固定的,而是随着需要传递的,可变参数的定义格式如下:
返回值类型 方法名称(类型 … 参数名称);
注:所有的可变参数接收之后都是以数组的形式保存下来的,所以直接按数组的方式接收
public class newDemo01
{
public static void main(String args[]){
System.out.println("没有传递参数时fun():");
fun();
System.out.println("传递一个参数时fun():");
fun(1);
System.out.println("传递五个参数时fun():");
fun(1,2,3,4,5);
}
public static void fun(int ... args){
for(int i=0;i<args.length;i++){
System.out.print(args[i]+"、");
}
}
}
foreach输出
数组的输出,一般都会采用for循环进行输出,但在JDK1.5之后为了方便数组的输出,提供了一种foreach语法,其格式如下:
for(数据类型 变量名称 : 数组名称){…..};代码如下:
public class newDemo02
{
public static void main(String args[]){
System.out.println("没有传递参数时fun():");
fun();
System.out.println("传递一个参数时fun():");
fun(1);
System.out.println("传递五个参数时fun():");
fun(1,2,3,4,5);
}
public static void fun(int ... args){
for(int x : args){
System.out.print(x +"、");
}
}
}
1、 以上的两种语法在开发中会经常的使用到,尤其是在进行一些其它引用数据类型使用可变参数的时候
2、 Foreach不只是可以输出在以后的类集中也是有输出能力的