JAVA系列之数组的秘密(数组的一般用法+力扣 斯坦福大学练习精解)
大佬们好呀~
更多精彩: 个人主页
JAVA专栏
文章目录
- 一、数组的概述
- 1.1什么是数组?
- 1.2注意:
- 1.3建议:
- 二、数组的定义
- 1.格式:
- 三、数组的静态初始化
- 1.数组的初始化:
- 2.静态初始化:
- 格式:
- 数组的长度:
- 四、数组的地址值
- 1.1地址值:
- 1.2拓展:
- 五、数组的元素访问
- 1.格式:
- 2.索引:
- 3.获取数组中的元素
- 4.把数据存入到数组中
- 六、数组的遍历
- 1.数组的遍历:
- 2.拓展:
- 3.练习:
- 3.1遍历数组求和
- 3.2条件变化
- 七、数组的动态初始化
- 1.动态初始化:
- 1.1信息存入:
- 1.1.1添加:
- 1.1.2获取:
- 1.2数组默认初始化值的规律
- 2.动态初始化与静态初始化的区别
- 八、数组的常见问题
- 九、数组的常用操作
- 1.求最值
- 2.遍历求和
- 3.交换数据
- 4.打乱数据
- 十、数组的内存图
- 1.java的内存分配
- 2.数据的内存图
前言
在 Java 编程中,我们经常要处理一系列数据,数组作为最基础、常用的数据结构,就像有序容器,能有效存储和管理数据。接下来,让我们深入探索 Java 数组,从基础到高级,掌握这一关键知识,助力 Java 编程。
一、数组的概述
1.1什么是数组?
数组指的是一种容器,可以用来存储同种数据类型的多个值。
1.2注意:
这里在存储数据的时候要注意隐式转换。
int 类型的容器可存储(byte,short,int)
double 类型的数组容器可储存(byte,short,int,long,float,double)
(大)double>float>long>int>short>byte(小)
大可以储存小(隐式转换),小不可以储存大!(强制转换)
1.3建议:
容器的类型和存储的数据类型保持一致~!
二、数组的定义
1.格式:
格式:
数据类型 [] 数组名 或 数据类型 数组名 []
int [] arry 或 int arry []
[]
此符号代表定义的是一个数组
,不写代表定义的是一个变量
三、数组的静态初始化
1.数组的初始化:
初始化:就是在内存中,为数组容器开辟空间,并将数组存入容器中的过程。
包括:静态初始化和动态初始化
2.静态初始化:
数组的内容是固定的已知的。
格式:
完整格式:
数据类型 [] 数组名 = new 数据类型[]{元素1,元素2,元素3......};
int [] nums = new int [] {1,2,3,4,5};
简化格式:
数据类型[] 数组名={元素1,元素2};
int arry []={1,2,3};
数组的长度:
arry : 长度为3
11 | 22 | 33 |
---|
四、数组的地址值
当我们定义一个数组,其中含有三个元素(1,2,3),打印出这个数组arry.
eg:
int arry []={1,2,3};
System.out.println(arry);
运行展示:
[I@10f87f48
运行出来会出现一段乱码,当然乱码并不是真的乱码,而是数组的地址值
1.1地址值:
就是表示数组在内存中的位置。
1.2拓展:
解释一下地址值的格式含义:
[
:表示当前是一个数组
I
:表示当前数组里面的元素是int
类型的
@
:表示一个间隔符号(固定格式)
10f87f48
:这才是数组真正的地址值(十六进制)
平时我们习惯性的会把这个整体叫做数组的地址值
五、数组的元素访问
1.格式:
数组名[索引];
eg:
nums[0];
2.索引:
数值 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
索引(下标) | 0 | 1 | 2 | 3 |
特点:从0开始,逐个+1增长,连续不断
3.获取数组中的元素
int [] arr={11,12,13};
int num=arr[0];
System.out.println(num);
简单写法:
int [] arr={11,12,13};
System.out.println(arr[0]);
run:
11
4.把数据存入到数组中
格式:
数组名[索引]=具体数据/变量
arr[0]=100
public class boke {
public static void main(String[] args) {
int [] arr={11,12,13};
arr[0]=100;
System.out.println(arr[0]);
}
}
run:
100
细节:一旦覆盖之后,原来的数据就不存在了
六、数组的遍历
1.数组的遍历:
将数组中所有的内容取出来,取出来之后(打印,求和,判断)
注:遍历指的是取出数据的过程不要局限的理解为遍历就是打印
根据我们上文的学习,大家可能会想,我一个个使用arr[i]打印出来不行吗?
public class boke{
public static void main(String[]args){
int [] arr={1,2,3,4,5};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
}
}
run:
1
2
3
4
5
虽然这样一个一个println
也可以遍历出数组的数据,可是当数组的数据个数足够庞大时我们应该怎么办呢?
我们想到了循环:将索引换成变量i,然后再循环打印arr[i]
我们来做一下代码实现:
int [] arr={11,12,13};
for (i=0;i<=4;i++){
System.out.println(arr[i]);
}
我们在写循环时可能会遇到数组长度的问题,我们有一个官方写法:
调用方式:
数组名.length
System.out.println(arr.length);
//打印数组的长度
2.拓展:
自动的快速生成数组的遍历方式
由IDEA提供的,数组名.fori
回车,就会出现以下代码。
for (int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
3.练习:
3.1遍历数组求和
//将数组中的11,22,33,44,55,66,77,88,99求和
public class bianli{
public static void main (String[]args){
int [] num ={11,22,33,44,55,66,77,88,99};
int sum = 0;
for (int i=0 ; i<num.length ; i++){
sum+=num[i];
}
System.out.println(sum);
}
}
3.2条件变化
//如果是奇数,将当前数字扩大两倍,偶数将当前数字变成1/2
int [] num={1,2,3,4,5,6,7,8,9,10};
for (i=0 ; i<num.length ; i++){
if (num[i]%2==0){
num[i]/=2;
}else{
num[i]*=2;
}
System.out.println(num[i]);
}
一般情况下,一个循环只做一件事,于是我们可以优化一下
int [] num={1,2,3,4,5,6,7,8,9,10};
for (i=0 ; i<num.length ; i++){
if (num[i]%2==0){
num[i]/=2;
}else{
num[i]*=2;
}
}
for (i=0 ; i<num.length ; i++){
System.out.println(num[i]);
}//重新遍历一下
七、数组的动态初始化
1.动态初始化:
初始化时只指定数组长度,由系统为数组分配初始值。
格式:
数据类型[]数组名=new 数组类型[数组长度];
int [] arr = new int [3];
//先建立一个空壳,[3]说明只能存3个int类型的整数
在创建的时候,有我们自己指定数组的长度,由虚拟机给出默认的初始值。
1.1信息存入:
1.1.1添加:
arr[0]=3;
1.1.2获取:
System.out.println(arr[1]);
run:0(默认初始化值)
1.2数组默认初始化值的规律
整数类型:默认初始化值0
小数类型:默认初始化值0.0
字符类型:默认初始化值‘/u0000’空格
布尔类型:默认初始化值false
引用数据类型:默认初始化值null
2.动态初始化与静态初始化的区别
动态
:
含义:手动指定数组的长度,由系统给出默认初始化值
只明确元素的个数,不明确具体数值,推荐使用动态初始化
eg:
使用数组容器来存储键盘录入的5个整数
int [] arr = {????};
int [] arr = new int[5]
静态
:
含义:手动指定数组元素,系统会根据元素个数,计算出数组的长度。
需求中已经明确了要操作的具体数据,直接静态初始化即可。
eg:
将全班 的学生成绩存入数组中11,22,33
int [] nums= {11,22,33};
八、数组的常见问题
索引越界异常:访问了不存在的索引
索引的范围:0~数组的长度-1
九、数组的常用操作
1.求最值
//已知数组元素为{33,5,22,44,55},请找出数组中最大的值并打印在控制台。
public class wenti {
public static void main(String[] args) {
int [] best ={33,5,22,44,55};
int max = best[0];//记录数值的变化
for (int i = 0; i < best.length; i++) {
//遍历数组中的每一个元素,让他和max比较,如果找到更大的就记录
if (best[i]>max) {
max = best[i];
}
}
System.out.println(max);
}
}
2.遍历求和
//生成10个1-100之间的随机数存入数组
//求出所有数据的和
//求出所有数据的平均数
//统计有多少个数据比平均数小
import java.util.Random;
public class suym {
public static void main(String[] args) {
Random rand = new Random();
int [] num = new int[10];
int sum = 0;
int count = 0;
for (int i = 0; i < 10; i++) {
int x = rand.nextInt(100)+1;
num[i] = x;
sum += x;
System.out.println(x);
if (num[i] < sum/10){
count++;
}
}
System.out.println("生成随机数的和为:"+sum);
System.out.println("生成随机数的平均数为:"+sum/10);
System.out.println("小于平均数的个数为:"+count);
}
}
3.交换数据
//将数组{1,2,3,4,5}顺序交换
public class jiaoone {
public static void main(String[] args) {
int [] arr={1,2,3,4,5};
//从两头开始遍历,然后交换
for(int i=0 , j=arr.length-1 ; i<j ; i++,j--){
//找一个工具人,方便交换
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
for (int i = 0; i < arr.length; i++) {
//print同行打印
System.out.print(arr[i]+" ");
}
}
}
4.打乱数据
//需求:将数组打乱
import java.util.Random;
public class da {
public static void main(String[] args) {
//导入随机数
Random ran=new Random();
int random=ran.nextInt(nums.length);
int [] nums={1,2,3,4,5};
for (int i = 0; i < nums.length; i++) {
//遍历数组拿着它和随机索引交换
int temp=nums[i];
nums[i]=nums[random];
nums[random]=temp;
}
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i]+" ");
}
}
}
十、数组的内存图
1.java的内存分配
注:从JDK8
开始,取消方法区,新增原空间,把原来方法区的多种功能拆分,有的功能放到了推中,有的功能放到了元空间中。
栈
:方法运行时使用的内存,比如main方法运行进入方法栈中执行。
堆
:存储对象或者数组,new来创建的,都存在堆内存
方法区
:存储可以运行的class文件
本地方法栈
:JVM在使用操作系统功能的时候,和我们开发无关。
寄存器
:给CPU使用,和我们开发无关
2.数据的内存图
通过arr找到地址值,再通过索引找到数组内容。
注:
1.只要是new
出来的一定是在推里面开辟了一个小空间
2.如果new
了多次,那么在堆里面有多个小空间,每个小空间中都有各自的数据。
两个数组指向同一个空间的内存图:
注:当两个数组指向同一个小空间时,其中一个数组对小空间中的值发生了改变,那么其他数组再次访问的时候都是修改之后的结果了。