1.数组的基本定义
数组的定义有两种
动态初始化语法:
- 数据类型[] 数组名 = new 数据类型[长度];
- 数据类型 数组名[] = new 数据类型[长度];
例子:
public class Test {
public static void main( String[] args ){
int[] arr = new int[5];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
for (int i : arr) {
System.out.println(i);
}
}
}
看上面的代码,定义了5个数组空间,因为是动态初始化的所以需要单个为每个数组空间赋值,而数组空间的下标是从0开始的,我定义了5个数组空间对应的就是0,1,2,3,4。
静态初始化语法:
- 数据类型[] 数组名 = new 数据类型[]{值,值…};
- 数据类型[] 数组名 = {值,值…};
例子:
public class Test {
public static void main( String[] args ){
int[] arr = {1,2,3};
for (int i : arr) {
System.out.println(i);
}
}
}
静态初始化和动态初始化区别不大,前者是在开辟空间的时候赋值,后者是在开辟空间后赋值,如果硬是要分的话静态初始化代码少一点。
总结
注意数组长度都是固定的
因为数组是引用类型,所以不管再怎么定义数组都要先开辟空间,如果引用了没有开辟空间的数组会报空值错误。
在java中有一种获取数组长度的方式:数组名.length
例子:
public class Test {
public static void main( String[] args ){
int[] arr = {1,2,3};
System.out.println(arr.length);
}
}
2.数组引用传递分析
下面给大家分析一下引用传递。
引用传递是传递地址,也就是可以被修改的。
上代码:
public class Test {
public static void main( String[] args ){
int[] arr = {1,2,3};
int[] arrA = arr;
arrA[0] = 10;
for (int i : arr) {
System.out.println(i);
}
}
}
输出结果:
10
2
3
根据图片来分析,因为数组是引用传递,所以当arrA = arr的时候都会指向同一个地址,当有一个进行更改值的时候另一个拿到的值是更改后的值了。
这就是引用传递,它不会为你重新开辟一个空间把相同的值传递过去,而是共同使用一个地址指向的空间。
3.foreach输出
foreach:增强for循环,用于循环输出
语法:
for(数据类型 变量名 : 遍历对象){
…代码块
}
上代码
public class Test {
public static void main( String[] args ){
int[] arr = {1,2,3};
for (int i : arr) {
System.out.println(i);
}
System.out.println("");
for(int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
}
}
这样一看是不是感觉foreach方便一点
4.二维数组
首先了解一下什么是一维数组,一维数组就是储存一组相同数据类型的容器。而二维数组则是储存一维数组的容器,二维数组里面的元素全部都是和数据类型相同数组不能储存其他的数据类型数组。
语法:
- 数据类型[] [] 数组名 = new 数据类型[二维数据储存数][一维数组的长度];
- 数据类型[] [] 数组名 = {{值,值…},{值,值…}};
二维数组内存
如上图,一维数组把内存地址存入到二维数组中。
二维数组初始化:
public class Test {
public static void main( String[] args ){
//初始化一个二维数组里面有三个一维数组
int[][] arrA ={{1,1,2},{1,2,3},{3,2,1}};
//初始化一个二维数组里面定义了3个一维数组都是为null,没有限制一维数组的长度
int[][] arrB = new int[3][];
arrB[0] = new int[]{1,2,3,4};
arrB[1] = new int[]{1,2,3};
arrB[2] = new int[]{1,2};
}
}
二维数组遍历:
public class Test {
public static void main( String[] args ){
//初始化一个二维数组里面有三个一维数组
int[][] arrA ={{1,1,2},{1,2,3},{3,2,1}};
for (int[] is : arrA) { //遍历二维数组
for (int i : is) { //遍历一维数组
System.out.print(i);
}
System.out.println("");
}
System.out.println("----------------------------------");
//初始化一个二维数组里面定义了3个一维数组都是为null,没有限制一维数组的长度
int[][] arrB = new int[3][];
arrB[0] = new int[]{1,2,3,4};
arrB[1] = new int[]{1,2,3};
arrB[2] = new int[]{1,2};
for (int i = 0; i < arrB.length; i++) { //遍历二维数组
for (int j = 0; j < arrB[i].length; j++) { //遍历一维数组
System.out.print(arrB[i][j]);
}
System.out.println("");
}
}
}
5.数组与方法
数组可以被方法当成参数传递或者当成返回值,但是由于数组是引用类型,所以在方法参数中被传递当值被修改了,所有调用当前数组的都会拿到修改后的值。
public class Test {
public static void main( String[] args ){
int [] arr = new int[]{1,2,3};
show(arr);
for (int i : arr) {
System.out.println(i);
}
}
public static void show(int [] arr){
arr[0] = 10;
}
}
输出结果:10 2 3
6.数组排序案例分析
冒泡排序:
public class Test {
public static void main( String[] args ){
//初始化一个数组
int [] arr = new int[]{10,23,3,22,1,100,2,2};
//创建两个循环
for (int i = 0; i < arr.length-1 ; i++) { //外循环
//-i是因为每次比较会把数组内最大值都放到最后,也就不用比较了
//-1因为数组长度是从0开始算,如果不-1就会造成数组越界
for(int j = 0; j < arr.length-i-1; j++ ){ //内循环
int temp = 0; //空值 用来存放要替换的值
if (arr[j]>arr[j+1]) { //比较第1个是否大于第2个值
temp = arr[j+1]; //进行替换
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
for (int i : arr) {
System.out.println(i);
}
}
}
冒泡排序就是用数组第1个值比较第2值,如果第1个比第2个值小就不用替换,往后继续第2个值比较第3个值,如果第2个值比第3个值大,那就把第2个值和第3个值相互替换,随后继续用第3个值比较第4个值…以此推类,直到替换为最后一个,因为已经全部比较完最后一个是最大的了所以最后一个就不用在比较了节省时间。
我刚刚演示的是正序,如果要倒序反过来就行了
7.数组转置案例分析
转置有两种方法首先给大家介绍第一种:
第一种就比较简单,准备两个数组,在for循环里面让第一个数组用下标从最后一位开始遍历,赋值到第二个数组,然后在再获取第二个数组的地址。
public class Test {
public static void main( String[] args ){
int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
int[] arrA = new int[arr.length];
int num = arr.length-1; //数组下标
for (int i : arr) {
System.out.print(i);
}
for (int i = 0; i < arr.length; i++) {
arrA[i] = arr[num]; //进行转置
num--;
}
arr = arrA; //获取地址
System.out.println("");
for (int i : arr) {
System.out.print(i);
}
}
}
这样的话比较麻烦循环次数太多,还浪费资源。不推荐
这种的我就不画图了(^ _ ^)
第二种:
这种的话就比较方便,只要一个数组就行了,准备4个变量分别是循环次数,用来存储的空值,开始的下标和最后的下标。因为是把前面的值和后面的值互换所以循环次数不用全部把数组长度对折就是循环次数了,然后值互换和冒泡排序一样就行了。
public class Test {
public static void main( String[] args ){
int[] arr = new int[]{1,2,3,4,5,6,7,8,9};
int count = arr.length/2; //循环次数
int hrad = 0; //开始的下标
int tail = arr.length-1; //最后的下标
for (int i = 0; i < count; i++) {
int temp = 0;
//互换
temp = arr[hrad];
arr[hrad] = arr[tail];
arr[tail] = temp;
hrad++;
tail--;
}
for (int i : arr) {
System.out.print(i+"_");
}
}
}
输出结果:9_8_7_6_5_4_3_2_1_
每次循环前后互换一次。
8.数组相关类库
import java.util.Arrays;
public class Test {
public static void main( String[] args ){
//排序
int[] arr = {212,1,23,22,3,2};
Arrays.sort(arr);
for (int i : arr) {
System.out.println(i);
}
//比较两个数组是否相等
int[] arr2={1,3,4,5,6,7};
System.out.println(Arrays.equals(arr,arr2));
}
}
常用的类库就是java.util.Arrays。
9.方法可变参数
语法:
修饰符 返回值 方法名(数据类型 …变量名){
方法体
}
public class Test {
public static void show(int ...is){
for (int i : is) {
System.out.println(i);
}
}
public static void main( String[] args ){
show(1,2,3,4,5,6);
}
}
原理:
底层是数组,所以输出的时候也是用数组的方式输出比如说循环,可变参数可以一直累积.
注意:
可变参数只能在方法的参数列表里定义,只能定义在参数列表里的最后一个参数
每个方法只能定义一个可变参数
10.对象数组
数组可以存储相同类型的数据不止限制于数据类型,也可以是对象,接下来给大家介绍一下怎么使用。
class Cat {
private int age;
private String name;
public void show(){
System.out.println(1);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Test {
public static void main( String[] args ){
Cat[] carr = new Cat[5];
for (Cat cat : carr) {
//cat.show(); //会运行报错,因为对象数组里面存储的对象并没有new也就没有开辟内存空间
cat = new Cat(); //要new对象之后才能调用属性和方法
cat.show();
}
}
}
注意:
因为对象数组声明的都是没有开辟内存空间的对象所以不能调用,要想使用还是需要new才行。
所以数组初始化都是一样的