数组
目录
数组的动态初始化:初始化之后数组每一个元素的保存内容为其对应数据类型的默认值
数组都是引用数据类型,不管是不是Int这种基本数据类型,存放的数据类型相同**
一.数组
数组的动态初始化:初始化之后数组每一个元素的保存内容为其对应数据类型的默认值
声明并初始化数组
数据类型 数组名称 []= new 数据类型[长度]
数据类型 [] 数组名称 = new 数据类型[长度]
数据的静态初始化:在数组定义的时候为其设置好了里面的内容
简化格式: 数据类型 数组名称 []={数据1,数据2,数据3}
完整格式: 数据类型 数组名称 []=new 数据类型[]{数据1,数据2,数据3}
数组都是引用数据类型,不管是不是Int这种基本数据类型,存放的数据类型相同**
数组操作中,在栈内存中保存永远都是数组的名称,只开辟了栈内存空间的数组是永远无法使用,必须有指向的堆内存才可以使用,要想开辟新的堆内存必须使用new关键字,然后只是将堆内存的使用权交给了对应的栈内存空间,而且一个堆内存空间可以同时被多个栈内存空间所指向,即一个人可以有多个名字,一个具体的人就相当于堆内存,名字相当于栈内存
8种基本数据类型都是直接存放在内存中的内存栈中。数据本身的值就是存在栈空间里面,引用数据类型放不下,只能把声明存放到栈里面,然后保存一个地址,“引用”(存储对象在内存堆上的地址)是存储在有序的内存栈上的,而对象本身的值存储在内存堆上的。
声明数组放在栈中 int[] nums;
实例化数组 (开辟一块空间,没有存放在栈里面)nums=new int[5];//开辟一个5个长度的空间,将这个空间的地址赋值给nums;
给数组分配空间放在堆中 a=new int[5];//a存放的是地址
数组的赋值和取值都是通过下标0来获取的
动态初始化:先定义在赋值
静态初始化:定义的同时就进行赋值
boolean 类型默认为false;
1.从键盘录入5个值并且打印
import java.util.Scanner;
public class ShuZu{
public static void main(String[] args){ //申明数组和实例化数组
int nums[]=new int[5]; //需要自己在键盘录入5个值,然后保存到数组里面,并且打印出来 Scanner scan=new Scanner(System.in); //使用循环来录入值赋值给数组里面的每一个元素 for(int i=0;i<nums.length;i++){
System.out.println("请输入第"+(i+1)+"个值:");
nums[i]=scan.nextInt();
} //打印数组里面的内容
for(int i=0;i<nums.length;i++){
System.out.println(nums[i]);
}
}
}
2.增强for循环,通过foreach--只做遍历
for(元素的类型 元素的变量:指定的数据的变量名){
String[] books= new String[4];
//通过索引就行赋值
books[0]="三国演义";
books[1]="西游记";
books[2]="水浒传";
books[3]="红楼梦";
//通过for循环遍历
for(int i=0;i<books.length;i++) {
System.out.println(books[i]);
}
//通过foreach遍历
for(String book:books) {
System.out.println(book);
}
}
}
public class ShuZu02{ public static void main(String[] args){
//增强for循环.专门针对数组和集合
int nums[]=new int[5];//每一次从nums数组里面,获取他的一个元素,从下标0开始一直到下标4结束 for(int num:nums){
System.out.println(num);
}
}
}
3.数组的练习
计算数组里面的和
public class ShuZu03{
public static void main(String[] args){
int nums[]={1,2,54,86}; sum1(nums); sum2(nums); avg1(nums); avg2(nums);
//计算数组里面所有元素的和
}
public static void avg2(int nums[]){
System.out.println(sum1(nums)/nums.length);
}
public static void avg(int nums[]){
int count=0;
for(int i=0;i<nums.length;i++){
count+=nums[i];
}
System.out.println(count/nums.length);
}
public static int sum1(int nums[]){
int count=0;
for(int num:nums){
count+=num;
}
System.out.println(count);
return count;
}
public static void sum2(int nums[]){
int count=0; for(int i=0;i<nums.length;i++){
count+=nums[i];
}
System.out.println(count);
}
}
二.数组类型的参数
1.传值(基本数据类型):传的是一个数值(传值)
public class ShuZu05{
public static void main(String[]args){
int number=10; //调用方法的时候会把number的值传递到方法里面
test1(number);//-》test(10);调用方法的时候,进行传值(所有的基本数据类型) System.out.println(number);
}
public static void test1(int number){
//在这里对number进行修改,不会影响我们调用的时候的变量 number+=20; //在这个方法的作用里面,number的值为30
}
}
//打印结果为10
2.int number=10;
test1(number);
System.out.println(number);
}
public static int test1(int number){
return number+=20;
}
}
//结果为10
2.传引用(引用数据类型):统统传的是一个地址(传址/传引用地址/传引用)
三.数组的扩容
创建大于原数组长度的新数组,将原数组的元素依次赋值到新数组中。
int[] nums={5,5,5,5};//nums其实存放的是一个地址(00xx) test1(nums);//调用方法传给方法其实就是00xx.test1方法已经把地址为00xx的值进行修改
for(int n:nums){
System.out.println(n);
}
}
public static void test1(int[] arrs){//arrs:得到其实就是一个00xx的地址
//对这个数组的每一个值都要加10
for(int i=0;i<arrs.length;i++){
arrs[i]+=10;//对00xx地址的值去进行修改,同样改的是,ooxx地址的值
}
}
}
//打印结果15 15 15 15
1.基本的数组扩容例子
public class ShuZu04{
public static void main(String[]args){
int[] nums={1,2,3,4,5}; //需要在保存一点值给nums数组里面
int[] arrs=new int[10]; //保证新数组的长度比原数组的长度长
for(int i=0;i<nums.length;i++){
arrs[i]=nums[i];//完成了值的拷贝内容
}
//打印一个新数组的内容
for(int ar:arrs){
System.out.println(ar+",");
}
//需要将原数组扩容,虽然扩容,但是原数组只有5个长度 nums=arrs;//把arrs赋值给Nums就行
for(int num:nums){
System.out.println(num+",");
}
}
}
//打印结果:1,2,3,4,5,0,0,0,0,0,1,2,3,4,5,0,0,0,0,0
2.数组扩容2倍长度例子的方法
public class ShuZu04{ public static void main(String[]args){
int[] ss=new int[]{
6,5,4,3,2,1};
System.out.println(ss.length); //我们需要对ss进行扩容 ss=kuorong(ss); System.out.println(ss.length);
} //传入一个旧的数组,然后返回一个新的长度的数组 //新的数组的长度是原数组长度的2倍
public static int[]kuorong(int[] nums){ //创建新的数组长度是原数组长度的2倍
int []arrs=new int[nums.length*2]; //将原数组的值赋值给新的数组 for(int i=0;i<nums.length;i++){
arrs[i]=nums[i];
}
return arrs;
//返回值
}
}
打印结果;6,12
3.数组随意指定长度大小的例子
int[] ss=new int[]{6,5,4,3,2,1};
System.out.println(ss.length); //我们需要对ss进行扩容
ss=kuorong(ss,20);
System.out.println(ss.length);
} //传入一个旧的数组,然后返回一个新的长度的数组 //新的数组的长度是原数组长度的2倍
public static int[]kuorong(int[] nums,int newLength){
//指定的新数组的长度比旧数组长度小,返回空
if(nums.length>=newLength){
return null;
}
//创建新的数组长度是原数组长度的2倍
int []arrs=new int[newLength]; //将原数组的值赋值给新的数组
for(int i=0;i<nums.length;i++){
arrs[i]=nums[i];
}
return arrs;
}
}
四.数组的复制
新建一个更长的数组,然后将原数组的值赋值给新数组。这里是将数组的引用地址复制给数组变量
4.1System.arraycopy(src, srcPos, dest, destPos, length);
/* @param src the source array.源数组
-
@param srcPos starting position in the source array.源数组要复制的起始位置
-
@param dest the destination array.目标数组(将原数组复制到目标数组)
-
@param destPos starting position in the destination data.目标数组起始位置(从目标数组的哪个下标开始复制操作)
-
@param length the number of array elements to be copied.复制源数组的长度*/
public class ShuZuJDK{ public static void main(String[] args){ test1(); } public static void test1(){ int[] nums={5,4,6,1,2}; int[] arrs=new int[5]; //实现一下jdk的复制数组的方法 System.arraycopy(nums,0,arrs,0,nums.length); for(int ar:arrs){ System.out.print(ar+","); } } }
打印结果:5,4,6,1,2
4.2Arrays.copyOf(original, newLength);复制并且扩充长度
/* original -- 这是要被复制的数组。 newLength -- 这是要返回的副本长度。 */
test2(); } public static void test2(){ int nums[]={1,2,3,4,5}; //复制当前数组并且扩容新的长度 nums=Arrays.copyOf(nums,10);
for(int num:nums){ System.out.print(num+","); } } }
打印结果:1,2,3,4,5,0,0,0,0,0
4.32.4 Arrays.copyOfRange(original, from, to)指定复制
/* original 参数表示源数组 from 参数表示开始位置(取得到) to 参数表示结束位置(取不到) */
test3(); } public static void test3(){ int[] nums=new int[]{7,7,8,6,5}; //第一个参数是原数组。第二个参数是从哪个下标开始,第三个参数实到哪个下标结束(这个下标不会包括) int[] ns=Arrays.copyOfRange(nums,0,2); for(int n:ns){ System.out.print(n+","); } } }
打印结果:7,7
test3(); } public static void test3(){ int[] nums=new int[]{7,7,8,6,5}; //第一个参数是原数组。第二个参数是从哪个下标开始,第三个参数实到哪个下标结束(这个下标不会包括) int[] ns=Arrays.copyOfRange(nums,0,6); for(int n:ns){ System.out.print(n+","); } } }
打印结果:7,7,8,6,5,0,
最后需要注意的是基本类型的拷贝是不影响原数组的值的,如果是引用类型,就不能在这用了,因为数组的拷贝是浅拷贝,对于基本类型可以,对于引用类型是不适合的。
五.数组的排序
1.冒泡排序
排序思想:相邻俩元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在最后(如从小到大排序),下一次循环是将其他的数进行类似的操作
/*
-
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
-
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
-
针对所有的元素重复以上的步骤,除了最后一个。
-
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
-
随着比较的轮数的+1代表比较的次数-1
1.简易版
int nums[]={4,2,56,54,11,22,44,44,66,44,5,24}; //将数值里面的数字按大到小,按小到大进行排序
for(int i=0;i<nums.length;i++){ sort(nums);//执行一次方法把最大值找出来 } //打印一下数组 for(int num:nums){ System.out.print(num+","); } } //使用冒泡排序的方法 public static void sort(int[] nums){ //只做一件事,找到最大或者最小值,把它放在数组的最后面 //1.找到最大值或者最小值2.交换俩者的位置 //比较的是nums[i]和nums[i+1] //other=a;a=b;b=other; int other; //找到当前数组的最大一个,放在末尾 for(int i=0;i<nums.length-1;i++){ if(nums[i]>nums[i+1]){//交换俩者的位置 other =nums[i]; nums[i]=nums[i+1]; nums[i+1]=other; } } } }
结果:2,4,5,11,22,24,44,44,44,54,56,66,
2.正版
int nums[]={4,2,56,54,11,22,44,44,66,44,5,24}; //将数值里面的数字按大到小,按小到大进行排序
for(int j=0;j<nums.length-1;j++){//总共需要比较的轮数,-1是代表除自身和最大值,最大值已经出去了 int other; for(int i=0;i<nums.length-1-i;i++){//内循环;需要比较元素的个数,-i代表随着比较轮数的增加+1,需要比较元素的个数-1 if(nums[i]>nums[i+1]){ other =nums[i]; nums[i]=nums[i+1]; nums[i+1]=other; } } } for(int num:nums){ System.out.print(num+","); } } }
结果:2,4,5,11,22,24,44,44,44,54,56,66,
5.2 其他排序:
/* 选择排序: 第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。
插入排序: 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
归并排序: 将序列每相邻两个数字进行归并操作(merge),形成floor(n/2+n%2)个序列,排序后每个序列包含两个元素将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素.重复步骤2,直到所有元素排序完毕
快速排序: (1)首先设定一个分界值,通过该分界值将数组分成左右两部分。 [2] (2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。 [2] (3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。 [2] (4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。 [2]
随机快排:
计数排序: */
5.3:JDK排序 . Arrays.sort(arrs);
int nums[]={4,2,56,54,11,22,44,44,66,44,5,24};
//jdk 默认排序按照升序
Arrays.sort(nums);
for(int num:nums){ System.out.print(num+","); } } }
结果:2,4,5,11,22,24,44,44,44,54,56,66,
六.可变长度的参数
语法: public void test(int... arrs){}
arrs:代表0个或者多个同类型的参数.
① 可变参数本质就是一个数组,arrs就是一个数组的引用地址(反编译工具查看源代码)
②一个方法 可以有可变参数和普通参数,但是可变参数必须放到参数列表末尾;
③ 一个方法 有且只能有一个可变参数;
test(1,2); } //代表当前方法,这个参数列表是可变的 public static void test(int...nums){ for(int i=0;i<nums.length;i++){ System.out.pritnln(nums[i]); }} }
结果:1,2
test(1,2,3);
} //代表当前方法,这个参数列表是可变的 public static void test(int...nums){ for(int i=0;i<nums.length;i++){ System.out.pritnln(nums[i]); }} }
结果为1,2,3