Java - 数组详解(图解数组的基本操作)
目录
首先
什么是数组
数组是一组地址连续、长度固定的具有相同类型的数据的集合,通过数组下标我们可以指定数字中的每一个元素
数组的定义和内存分配
在Java中通过(类型名[] 数组名)或(类型名 数组名[])申明一个数组,其中(类型名[] 数组名)方式声明数组是Java特有也是推荐使用的
数组是一个特殊的对象,所以在使用前需要在内存中开辟一块内存空间用来存放数据,否则会抛出空指针异常,可以通过(new)关键字给数组分配内存,也可以使用通过在静态初始化(见下)时隐式的给数组分配与初始化元素个数相同的数组空间
定义了一个数组后可以通过(数组名[下标])的方式访问数组中的数据,通过(数组名[下标]=数据)为数组赋值
数组的赋值和访问
数组的赋值有两种:静态初始化、动态初始化
- 静态初始化:通过(类型[] 数组名={元素,元素...})或(类型[] 数组名=[]{元素,元素...})的方式为数组初始化,数组将自动分配一个与元素个数相同的内存空间
- 动态初始化:通过(类型[] 数组名=new 类型[大小])为数组分配内存,通过(数组名[下标]=数据)为数组初始化赋值
数组的注意事项
- 数组的类型可以是基本数据类型和引用类型
- 数组的长度不可变
- 数组的属性(数组名.length)获取的是数组的容量,而不是数组中存储元素的个数
- 数组的下标从0开始,最后一个元素的下标是(length-1)
public static void main(String[] args) {
int[] arr1={1,2,3};//定义一个int类型数组arr1,静态初始化数组,其数组长度为3
int[] arr2=new int[3];//定义一个长度为3的int类型数组arr2 int类型的数组其元素默认值是0
int[] arr3=new int[]{4,5,6};//定义一个int类型数组arr2,并静态初始化数组,其数组长度为3 //(数组名.lenth)获取数组的容量大小
System.out.println("arr1的长度为 : "+arr1.length+" - ["+arr1[0]+", "+arr1[1]+", "+arr1[2]+"]");
System.out.println("arr1的长度为 : "+arr2.length+" - ["+arr2[0]+", "+arr2[1]+", "+arr2[2]+"]");
System.out.println("arr1的长度为 : "+arr3.length+" - ["+arr3[0]+", "+arr3[1]+", "+arr3[2]+"]");
}
数组的内存图解
数组的遍历
我们常使用for循环或foreach遍历数组:见代码
public static void main(String[] args) { int[] arr={1,2,3};
// 使用for循环遍历数组
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+", ");
}
System.out.println("\n-----快乐的分割线-----");
// 使用foreach遍历数组
/*
* foreach的用法
* for(数组类型 变量名 : 数组名){
* 通过 变量名 访问数组中的每个元素
* }
*/
for(int i : arr){
System.out.print(i+", ");
}
}
好了,经过了对数组的简单了解后,让我们看看对数组的基本操作
插入
我们知道,通过(数组名[下标]=数据)的方式能很容易的给数组的任一位置赋值,但是如果原位置本含有数据,此时就会将原有数据覆盖,也就造成了数据丢失
所以我们可以将插入位置及之后的所有实际使用元素都向后移动一位,这样插入位置就空出来(当然也需要有足够的剩余空间,不然也是不能插入的),我们就可以插入需要的数据啦。那么怎么将插入位置及之后的实际使用的元素都后移呢,只要我们从(实际存储的最后一个元素位置+1)开始,从后往前遍历数组,将数组的前一个值赋给后一个位置,直到插入位置,这样插入位置就空出来了
当然我们还有一个小问题,因为之前说过length属性只能获得数组的容量大小,而不是实际使用的空间大小,但是在插入过程中我们需要从(实际存储的最后一个元素位置+1)进行操作,也就是我们需要获得数组的实际使用空间,怎么办呢?很容易,只要定义一个变量用来记录数组中的元素个数,当插入元素时(个数+1),当删除元素时(个数-1)就可以了
为了更清楚的理解插入操作,先上图
上代码:
public class ArrayOperate { /** 给数组一个容量 此处给个5*/
private int capacity = 5;
/** 定义一个数组 数组长度为capacity给定 5*/
private int[] arr = new int[capacity];
/** 用来存储数组的实际使用空间 */
private int count; /**
* 向数组中index下标处插入元素
*/
public boolean insert(int index,int inner){
//---------------------【在index下标处插入元素 - 关键代码】
if(this.count>=this.capacity){
// 当实际元素个数等于数组容量时 数组已满 不能插入
System.err.println("数组已满");
return false;
}
if(index<0||index>count){
// 当插入位置不在(0和count)之间时 不能插入数据
System.err.println("请在 0-"+count+"之间插入数据");
return false;
} for(int i=count;i>index;i--){
this.arr[i]=this.arr[i-1];// 数组元素依次向后移动
}
this.arr[index]=inner;//给数组index下标处赋值插入元素
count++;//插入数据后 实际大小需要+1
return true;
} /** 在数组的后面添加元素 */
public boolean append(int inner){
/*
* 在数组的后添加元素
* 我们可以这样写:
* if(this.count>=arr.length){
* return false;//先判断数组是否已满 如果满了就不允许插入元素了
* }
* if(index<0||index>count){
* return false;
* }
* arr[count]=inner;//为数组赋值【因为数组的下标是从0开始的,所以数组的实际添加的最后一个位置是count-1,所以如果需要在后面添加元素的话arr[count]就可以了】
* count++;
* return true;
*/ // 但是因为在之前实现了在数组index位置插入元素的方法 我们只需要调用该方法就可以了
// 在数组count位置插入元素
return insert(count,inner);
} public static void main(String[] args) { // 测试
ArrayOperate arrs=new ArrayOperate();
// 为数组初始化元素
arrs.append(12);
arrs.append(10);
arrs.append(5);
arrs.append(20);
System.out.println(Arrays.toString(arrs.arr));// 打印初始化的数组元素
// 在数组的第二位置插入16
arrs.insert(1, 16);
System.out.println(Arrays.toString(arrs.arr));// 打印插入后的数组元素 } }
删除
既然有插入操作自然有删除,与插入相似,我们只需要将移动数据的部分反过来就可以了
上图
上代码
public boolean delete(int index){ // 判断数组是否为空了 如果为空,则不能再删除元素
if(count==0){
System.err.println("数组以空");
return false;
}
// 判断输入的下标是否超过指定范围 超过则不能再删除数据
if(index<0||index>=count){
System.out.println("请在 0-"+(count-1)+"之间删除数据");
return false;
}
// 从index开始,将后一个元素赋值给前面,知道到最后一个实际元素
for(int i=index;i<count-1;i++){//当最后一个元素时 应该是 arr[length-2]=arr[length-1]; 所以应该(i<length-1)
this.arr[i]=this.arr[i+1];
}
// 给最后一个元素补0
// 并将元素使用长度-1
this.arr[--count]=0; return true;
} public boolean delete(){
/*
* 同样的 我们可以调用之间写的delete(index)方法删除最后一个元素
* 也可以这样写
* if(count<=0){
* return false;
* }
* if(index<0||index>=count){
* return false;
* }
* arr[--count]=0;
* return true;
*/
return this.delete(count-1);
}
// 测试 -- 删除数组上的第二个元素
arrs.delete(1);
System.out.println(Arrays.toString(arrs.arr));
扩容
之前我们强调过,数组长度是固定的,那么我么怎么对数组进行扩容呢?其实只要重新创建一个数组,其长度比原有数组长度大n,并将原数组中的内容复制到新数组中,然后将新数组的地址引用赋给数组变量就能完成对原数组的扩容(不过因为每次都需要新创建一个数组并复制原数组的值,所以其性能会比较低)
看一个图
理解了这个,写代码就很容易了
/** 给数组扩充addLength个长度 */
public boolean exCapacity(int addLength){
if(addLength<0){
// 如果输入的长度小于0,则禁止扩容 因为参数是负数 其新创建的数组的长度比原数组要小,在下面的复制操作中会下标越界
System.err.println("请输入大于0的整数");
return false;
}
// 创建一个临时数组 其长度为本数组长度+扩充长度
int[] tp=new int[this.arr.length+addLength];
for (int i = 0; i < this.arr.length; i++) {
tp[i]=this.arr[i];// 将原数组内容复制到新数组中
}
this.arr=tp;// 将新数组的地址引用赋给数组变量
this.capacity=this.arr.length;// 扩容后将数组的长度赋值给capacity
return true;
}
反转
在题目中我们经常会遇到将一个数组反转,那么我们先分析一个例子,[1,2,3]的反转数组为[3,2,1],[1,2,2,1]的反转数组为[1,2,2,1],此时看来,将[1,2,3]的1,3交换就变成了[3,2,1],将[1,2,2,1]的1和1交换,2和2交换同样变成了反转数组;将反转一个数组其实只需要在数组的中心位置将两边的对称位置的元素进行交换就可以了
看图
代码
/** 反转数组 */
public void reverse(){
// 当为count时 只对实际存储的元素进行反转
// 当将count转换为arr.length时 会反转整个数组
for(int i=0;i<count/2;i++){
// 交换对称的两个元素
int a=arr[i];
arr[i]=arr[count-1-i];
arr[count-1-i]=a;
}
}
最后附上源码
https://files.cnblogs.com/files/wangbingc/ArrayOperate.rar
今天先讲到这里,第一次写博客ヾ ^_^♪如果有什么不对的, 欢迎大家指正,谢谢ლ(╹◡╹ლ)
Java - 数组详解(图解数组的基本操作)的更多相关文章
- Java基础之 数组详解
前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...
- “全栈2019”Java第三十一章:二维数组和多维数组详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第三十章:数组详解(下篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十九章:数组详解(中篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十八章:数组详解(上篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 3.awk数组详解及企业实战案例
awk数组详解及企业实战案例 3.打印数组: [root@nfs-server test]# awk 'BEGIN{array[1]="zhurui";array[2]=" ...
- JavaScript进阶(十)Array 数组详解
JS array 数组详解 数组的声明方法 arrayObj = new Array(); 的数组 ,并且第一位是5 数组的运算(传地址) var t2=new Array(); t2[0]=1; t ...
- Swift_数组详解
Swift_数组详解 点击查看源码 初始化 //初始化 fileprivate func testInit() { //空数组 var array = [Int]() print(array) arr ...
- (转)awk数组详解及企业实战案例
awk数组详解及企业实战案例 原文:http://www.cnblogs.com/hackerer/p/5365967.html#_label03.打印数组:1. [root@nfs-server t ...
随机推荐
- day049--jQuery文档操作示例
DOM操作(CRUD增改查删) 创建元素 $('span') // 创建一个span标签 后置插入操作 append(), appendTo() <!DOCTYPE html> < ...
- The 16th Zhejiang Provincial Collegiate Programming Contest Sponsored E.Sequence in the Pocket(思维题)
传送门 题意: 给出一个序列,你可以将任意一个数移到最前面: 求最少需要移动多少次,可以是此序列变成非递减序列: 思路: 定义 (ai,aj) 为逆序对 ( i < j , ai > aj ...
- python全栈开发中级班全程笔记(第二模块、第三章)(员工信息增删改查作业讲解)
python全栈开发中级班全程笔记 第三章:员工信息增删改查作业代码 作业要求: 员工增删改查表用代码实现一个简单的员工信息增删改查表需求: 1.支持模糊查询,(1.find name ,age fo ...
- codeforces-1142 (div1)
div1真难,现在就是后悔, 非常后悔 A.显然如果我们知道起点和终点是哪两个点,我们可以算出距离通过b / gcd(a,b)的方式求出需要走几步的. 并且数据范围似乎也允许我们这么做,所以直接枚举取 ...
- python模拟页面调度LRU算法
所谓LRU算法,是指在发生缺页并且没有空闲主存块时,把最近最少使用的页面换出主存块,腾出地方来调入新页面. 问题描述:一进程获得n个主存块的使用权,对于给定的进程访问页面次序,问当采用LRU算法时,输 ...
- Vue学习笔记一:初识Vue
目录 什么是Vue? 为什么要学习前端框架? MVC,MVP 和 MVVM 最简单的入门小案例 下载Vue.js 新建文件结构 写一个html 运行 可笑的小报错 Vue和MVVM 什么是Vue? V ...
- Python——使用第三方库Pillow生成图片缩略图
流程如下: 1.首先确认是否安装了pip 在命令提示符窗口下输入pip,如果Windows提示未找到命令,可以重新运行安装程序添加pip. 2.在命令提示符窗口下输入pip install Pillo ...
- linux学习------磁盘性能测试
测试服务器 1核1G配置 下载后放在你想测试的目录下,执行preparefile.sh准备测试文件,完成后执行runTest.sh执行测试,等待测试结果完成. {sysbench_bin}> ...
- ibatis .net $与#的区别
$与#的区别 SELECT * FROM TABLE WHERE Id = #id# 其中如果字段id为字符串类型,那么#id#表示的就是'id',也就是说会自动加引号.如果id为整型,那么#id#就 ...
- Linux基础 - 系统优化及常用命令
目录 Linux基础系统优化及常用命令 Linux基础系统优化 网卡配置文件详解 ifup,ifdown命令 ifconfig命令 ifup,ifdown命令 ip命令 用户管理与文件权限篇 创建普通 ...