Java数组

1.数组(array):

一种用于存储多个相同类型数据的存储模型。

一次性声明大量的用于存储数据的变量。

要存储的数据通常都是同类型的数据。

在java中,数组也是对象。数组中的元素可以是任意类型(基本类型或引用类类型),但同一个数组里只能存放类型相同的元素。

2.数组定义格式:

先使用一个已有的类型,然后加上中括号,组合成一个数组类型,然后再声明这个数组类型的变量。

数组类型的变量,也是引用类型变量,简称引用,它是可以指向对象的(数组对象)

1)格式一:

数据类型[] 变量名;

比如:int[] arr;表示:定义了一个int类型的数组,数组名为arr。

2)格式二:

数据类型 变量名[];

比如:int arr[];表示:定义了一个int类型的变量,变量是名为arr的数组。

3.数组初始化方式:

Java中的数组必须先初始化才能使用。

所谓初始化就是为数组中的数组元素分配内存空间,并为每个数组元素赋值。

1)动态初始化:

初始化时,只指定数组长度,由系统为数组分配初始值。

//格式
数据类型[] 变量名 =  new 数据类型[数组长度];
int[] arr = new int[10];
/*
解释int[] arr:
int说明数组中元素类型是int型
[]说明这是一个数组
arr为数组名称

解释new int[10]:
new为数组申请内存空间
int说明数组中元素类型是int型
[]说明这是一个数组
10表示数组长度,其实就是数组中的元素个数
*/

使用new关键字,来创建数组对象,中括号里面的数字,就是数组的长度。
String[] s = new String[2];//数组对象s中,最多存放2个String类型的数据

数组对象在内存中,就是一块连续的内存空间,在这个连续的空间中,可以存放多个类型相同的数据。

🌂:数组对象中都有哪些属性和方法可以使用?
Ⅰ、数组对象中只有一个属性(length),表示数组的长度。可以使用length属性,获取数组对象的长度。
Ⅱ、数组对象中的方法,只有从父类型Object中继承过来的方法。
Ⅲ、除此之外,数组对象中就没有其他属性和方法了。

🌂: 数组长度:
Ⅰ、是指在一个数组对象中,最多可以存放多少个同一类型的数据。
Ⅱ、必须在创建数组对象的时候就明确指定。
Ⅲ、一旦确定,就无法再改变。
Ⅳ、可以为0,但是不能为负数。

2)静态初始化:

初始化时,指定每个数组元素的初始值,由系统决定数组长度。

//格式一:
数据类型[] 变量名 = new 数据类型[] {数据1,数据2,数据3,……};
int[] arr = new int[] {1,2,3};

//格式二:
数据类型[] 变量名 = {数据1,数据2,数据3,……};
int[] arr = {1,2,3};

4.数组元素的访问:

1)数组变量的访问方式:

//格式
数组名

数组名就是数组变量,我们可以直接输出。

2)数组内部保存的数据的访问方式:

//格式
数组名[索引]

索引是数组中数据的编号方式,计算机习惯从0开始编号。用于访问数组中的数据使用,数组名[索引]等同于变量名。

数组对象在JVM的堆区中是一块连续的内存空间,并允许使用下标,设置或获取每一个内存空间的值。

数组的下标的区间为,[0,arr.length-1],假如数组的长度为length的话,那么数组下标的最小值为0,数组下标的最大值就是length-1。如果使用下标访问数组中元素的时候,下标的值超出了其可用范围,那么运行就会报错。

5.Java中的内存分配:

1)Java程序运行时,需要在内存中分配空间。

2)为了提高运算效率,就对空间进行了不同区域的划分。每一片区域都有特定的处理数据方式和内存管理方式。

3)栈内存:存储局部变量。

局部变量:定义在方法中的变量。使用完毕,立即消失。

4)堆内存:存储new出来的内容(实体、对象)。

每一个new出来的东西都有一个地址值。使用完毕,会在GC空闲时被回收。

数组在初始化时,会为存储空间添加默认值。
整数,默认值为0,
浮点数,默认值为0.0,
布尔值,默认值是false,
字符,默认值是空字符,
引用数据类型。默认值是null,表示不指向任何有效对象。

6.数组易错点:

1)索引越界:

访问了数组中不存在的索引对应的元素。

2)空指针异常:

访问的数组已经不再指向堆内存的数据。

7.数组遍历练习:

public class demo{
        public static void main(String[] args){
                int arr[] = {1,2,3,4,5,6};
                for (int x=0;x<6;x++){
                        System.out.println(arr[x]);
                }
        }
}

8.获取数组元素数量:

格式:

数组名.length
//比如:arr.length

9.数组常见操作:

1)获取最大值

public class Max{
        public static void main(String[] args){
                int[] arr = {12,13,23,35};
                int max = arr[0];//定义一个变量max,用于存放数组中的最大值,并把数组中第一个数据作为变量的初始值
                /* 与数组中剩余数据逐个对比,每次将最大值保存到变量max中 */
                for(int i=0;i<arr.length;i++){
                        if(arr[i]>max)
                                max=arr[i];
                }
        System.out.printf("最大值:"+max);
        }
}

2)获取最小值

public class Min{
        public static void main(String[] args){
                int[] arr={12,13,14,1};
                int min=arr[0];
                for (int x=1;x<arr.length;x++){
                        if(arr[x]<min)
                                min=arr[x];
                }
        System.out.println("最小值:"+min);
        }
}


10.数组类型:

1)一般情况下,java中的类(class),是需要提前把代码写好,然后编译成class文件,再加载到内存中,最后在程序中就可以使用到这个类了。而数组和类不同,数组是使用当前已经存在的某一个类型(任意类型都可以),然后再这个类型后面加上一对中括号([]),这时就组成一个了新的类型:数组类型。

//任意类型 + [] = 相应的数组类型
byte + [] ---> byte[] 
short + [] ---> short[] 
int + [] ---> int[] 
long + [] ---> long[]
float + [] ---> float[] 
double+ [] ---> double[] 
char + [] ---> char[] 
boolean+[] ---> boolean[]
String+ [] ---> String[]

int[] + [] ---> int[][] //一维数组+[] 变为二维数组

2)数组中可以存放一组数据,要求这一组数据的类型是一样(或者兼容的,兼容就表示可以自动转换)。

例如,int类型数组(int[])中,也是可以存放byte数据的,因为byte可以自动转换为int(兼容)。

11.数组的默认值:

一个数组对象在创建的时候,需要指定数组长度,表示数组中最多存放的元素个数,并且在数组对象创建完成之后,数组中每一个元素位置上,就已经有了相应的默认值,这个默认值和数组的类型有关。

//byte、short、int、long类型数组中的默认值为 0 
int[] a = new int[4];//默认4个数据全是0 

//float、double类型数组中的默认值为 0.0
double[] d = new double[4];//默认4个数据全是0.0 

//boolean类型数组中的默认值为 false 
boolean[] d = new boolean[4];//默认4个数据全是false 

//char类型数组中的默认值为 '\u0000' 
char[] d = new char[4];//默认4个数据全是'\u0000' 

//引用类型数组中的默认值为 null 
String[] d = new String[4];//默认4个数据全是null

12. 数组拷贝:

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

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

//该方法的声明 
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
 //参数1,需要被复制的目标数组 
 //参数2,从目标数组的哪一个位置开始复制 
 //参数3,需要把数据复制到另外一个新的数组中 
 //参数4,把数据复制到新数组的时候,需要把数据从什么位置开始复制进去 
 //参数5,复制的目标数组的长度

13.工具类:

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

1)java.util.Arrays类:

①是JAVASE API中提供的一个工具类。

②作用:就是在代码中辅助我们对数组对象进行操作的。

里面有很多静态方法可以直接调用,主要的功能就是对数组对象进行操作,例如排序、查询、复制、填充数据等等。

2)Arrays中的常用方法:

toString():可以把一个数组变为对应的String形式。

copyOf():可以把一个数组进行复制。

该方法中也是采用了arraycopy方法来实现的功能。

copyOfRange():也是复制数组的方法,但是可以指定从哪一个下标位置开始复制。

该方法中也是采用了arraycopy方法来实现的功能 。

sort():可以对数组进行排序。

binarySearch():在数组中,查找指定的值,返回这个指定的值在数组中的下标,但是查找之前需要在数组中先进行排序,可以使用sort()方法先进行排序。

equals():可以比较俩个数组是否相等,但是要求俩个数组中的值一一相等并且顺序也要一致才行,所以在比较之前,最好是用sort方法对俩个数组先进行排序。

第一个要求:俩个数组的元素个数相同 。
第二个要求:俩个数组的每个下标对应的数据相同。

fill():可以使用一个特定的值,把数组中的空间全都赋成这个值。
asList():可以把一组数据,封装到一个List集合中,并且把list集合对象返回。

14.冒泡排序:

1)思想:

在一组数据中,从左到右,俩俩比较,然后把较大的数据往右推,一轮下来之后,最大的一个数据就被推到了最右边。

2)方法定义:

//定义一个冒泡排序的方法,参数是int[],该方法可以对数组进行排序,该方法不需要返回值
public void test(int[] arr){ 
	//获取到数组的长度 
	int len = arr.length; 
	//外层循环控制一共比较几轮
	for(int i=0;i<len-1;i++){ 
		//内层循环控制每轮比较多少次数,每轮比较的次数是有变化的
		for(int j=0;j<(len-i-1);j++){ 
			//比较俩个相邻数据的大小
			//如果前一个数据比后一个数据大
			if(arr[j]>arr[j+1]){ 
				//交互这个俩个数据的位置 
				arr[j] = arr[j] ^ arr[j+1]; 
				arr[j+1] = arr[j] ^ arr[j+1]; 
				arr[j] = arr[j] ^ arr[j+1]; 
			} 
		}
			//这个输出,可以看到每一轮比较结束后的结果是怎样的
			System.out.println("\t"+Arrays.toString(arr)); 
	} 
}

15.选择排序:

1)思想:

每一轮在待排序的区域中比较找到一个最小值后,把这个最小值放到已经排好顺序的区域的末尾,剩下的部分,组成一个新的待排序部分,重复上面的步骤直到排序结束。

🌂:操作的核心目标:
Ⅰ、每轮找到的最小值应该存放的下标位置是什么 。
Ⅱ、每轮找到的最小值现在的下标位置是什么 。
Ⅲ、找到之后,让这俩个位置的值进行交互就可以了 。
Ⅳ、最后一个数字就不用在比较了(前面都排好了,最后一个一定是最大的)。

2)方法定义:

//实现一个方法,参数是int[],该方法可以对数组进行排序,该方法不需要返回值。
public void test(int[] arr){ 
	//数组的长度 
	int len = arr.length; 
	//min_now_index表示最小值当前在什么位置 
	int min_now_index; 
	//min_should_index表示最小值应用在什么位置 
	int min_should_index;
	//外层循环,控制一共要比较多少轮,同时这个变量i,刚好是每轮我们需要指定的最小值应该存放位置。
	for(int i=0;i<len-1;i++){ 
		//每一轮i的值,刚好就是本轮最小值应该存放的位置。 
		min_should_index = i; 
		//假设当前i的位置就是本轮最小值的实际位置 
		min_now_index = i;
		//内层循环,负责每轮找出当前未排序区中的一个最小值的实际位置的下标
		for(int j=i+1;j<len;j++){ 
			//哪个数据小,就把这个数据下标赋值给min_now_index,目的是让了min_now_index变量中始终保持当前未排序区中的最小值的位置 
			if(arr[j]<arr[min_now_index]){ 
				min_now_index = j;
			} 
		}

//内层循环结束后,就明确了当前未排序区中的最新值的下标,以及这个最小值应该存放在什么位 置,接下来可以进行交互位置 
		if(min_now_index != min_should_index){ 
			int temp = arr[min_now_index]; 
			arr[min_now_index] = arr[min_should_index]; 
			arr[min_should_index] = temp; 
		} 
	} 
}

16.插入排序:

1)思想:

把数组分成俩部分,将后面部分的数据一个一个的和前面部分数据的元素进行比较,如果我们指定的元素比前面部分的元素小,那么就将前面的元素往前移动一步,直到没有比我们这个指定元素还小元素了,那么这个位置就是需要插入的地方。

比较的目的,是为了给当前操作的数字,找一个合适的位置进行插入,注意这个操作数字的位置,有可能是不需要移动的,因为刚好不移动就保持了正常顺序。

🌂:每轮操作完核心目标:
Ⅰ、拿到右边当前要操作的数据,这个值需要临时的保存起来,以便向左边插入合适的位置。
Ⅱ、找出左边一个合适的插入位置。
Ⅲ、最后把右边当前操作的数据,插入到左边合适的位置。
Ⅳ、注意,最后一个数字也需要进行比较,因为要插入到左边一个合适的位置。

2)方法定义:

public void test(int[] arr){ 
	//输出排序前的数组的排列 
	System.out.println(Arrays.toString(arr)); 
	//当前在右边拿到的第一个要进行操作的数据 
	int currentValue; 
	//需要把数据在左边插入的位置 
	int insertPosition;
	//外层循环,控制比较的轮数。同时,变量i的值,还是每一轮我们要操作的右边第一个数字的下标。
	for(int i=1;i<arr.length;i++){ 
		//提前保存好我们当前要操作的值 
		currentValue = arr[i]; 
		//假设当前变量i的值就是要插入的位置,因为这个数据有可能是原位置不动的。
		insertPosition = i;
		//内层循环,控制每轮比较的次数,以及比较的顺序。同时,变量j的值,还是左边数据中从大到小的下标值。
		for(int j=i-1;j>=0;j--){ 
			//每次比较,如果发现arr[j]比当前要操作的数字大 
			if(arr[j]>currentValue){ 
				//就把这个大的数字往后移动一个位置,就是往后赋值 
				arr[j+1] = arr[j]; 
				//然后记录一下这个位置,因为这个位置很可能是要插入的位置,到底是不是这个位置,需要和下一个数字比较后才知道
				insertPosition = j; 
			}else{
			//如果发现一个比currentValue值还小的值,那么这个值的上一个比较的位置就是我们要找的插入的位置,结束当前循环 
				break; 
		    } 
		}
		//内层循环结束后,把当前要操作的值currentValue,插入到指定位置insertPosition 
		//如果insertPosition和当前i值相等,说明当前操作的这个值currentValue是不需要移动 的。 
		if(insertPosition != i){ 
			//进行值的插入 
			//把当前右边第一个值(正在操作的值),插入到左边合适的位置 
			arr[insertPosition] = currentValue; 
		}
		//输出每一轮排序的过程 
		System.out.println("\t"+Arrays.toString(arr)); 
	}
	//最后输出排序的结果 
	System.out.println(Arrays.toString(arr)); 
}




笔试常考:数组的动态求和问题

/*
数组的动态求和
    输入:1,2,3,4,5
    输出:[1,3,6,10,15]

    首先要把输入的数据转为数组的形式存储
    1,2,3,4,5 => ["1","2","3","4","5"]

 */

import java.util.Scanner;

public class Test{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();

        String[] split = str.split(",");//以逗号的形式分割为数组
        int[] nums = new int[split.length];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = Integer.parseInt(split[i]);//Integer.parseInt()方法是将一个字符串转换为int数字,例如,"109" ==> 109
        }
        // nums => [1,2,3,4,5]
        // => [1,3,6,10,15]
        int[] res = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            int sum = 0;
            for (int j = 0; j < i + 1; j++) {
                sum += nums[j];
            }
            res[i] = sum;
        }

        for (int i = 0; i < res.length; i++) {
            System.out.println(res[i]);
        }
    }
}

优化后:

import java.util.Scanner;

public class Test {
   public static void main(String[] args) {
       Scanner sc = new Scanner(System.in);
       String str = sc.nextLine();

       String[] split = str.split(",");
       int[] nums = new int[split.length];
       for (int i = 0; i < nums.length; i++) {
           nums[i] = Integer.parseInt(split[i]);
       }
       // nums => [1,2,3,4,5]
       // => [1,3,6,10,15]
       int[] res = new int[nums.length];
       //i > 0      res[i] = res[i - 1] + nums[i]
       //i = 0      res[i] = nums[i]

       res[0] = nums[0];
       for (int i = 1; i < res.length; i++) {
           res[i] = res[i - 1] + nums[i];
       }

       for (int i = 0; i < res.length; i++) {
           System.out.println(res[i]);
       }
   }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值