数组作为一种组合形式的数据类型,必然要求提供一些处理数组的简便办法,包括数组比较、数组复制、数组排序等等。为此Java专门设计了Arrays工具,该工具包含了几个常用方法,方便程序员对数组进行加工操作。Arrays工具的方法说明如下:

		Arrays.equals(a1, a2); // 判断a1和a2两个数组是否相等,也就是每个元素是否都相等
Arrays.fill(a, val); // 往数组a全部填入指定的数值val
dest = Arrays.copyOf(src, newLength); // 把数组src的内容赋值给数组dest,且dest的长度为newLength
Arrays.sort(a); // 对数组a的内部元素进行排序,结果是按照升序排序

下面分别对以上的四个数组处理方法进行介绍:

1、Arrays.equals方法
前面说过,双等号“==”可用来判断两个变量的数值是否相等,但“==”只适合基本变量类型之间的比较,例如比较两个整型变量是否相等、两个双精度数是否相等、两个布尔变量是否相等。如果两个数组变量通过“==”进行相等判断,则比较的是这两个数组是否为同一个数组,而不是比较两个数组的所有元素是否都相等。要想判断两个数组内部的每个元素是否一一相等,就必须通过Arrays工具的equals方法来辨别。equals方法返回true表示两个数组的所有元素都相等,返回false表示两个数组至少有一个元素不相等。

2、Arrays.fill方法
在声明数组变量的时候,经常需要对它进行初始化赋值,比如书店进了十本书,每本书的售价都是99元,那么按照常规写法只能书写十遍99,就像下面代码这样:

		// 构造一个包含十个99的数组变量
int[] prices = {99, 99, 99, 99, 99, 99, 99, 99, 99, 99};

显然输入重复的数字是个负担,尤其重复数量很多的时候更甚。现在利用Arrays的fill方法,只需一行代码即可对该数组的所有元素都填上相同的数值,于是数组的初始赋值代码便优化为下面这样:

		// 声明一个整型数组,数组大小为10
int[] prices = new int[10];
// 给整型数组的每个元素全部填写99
Arrays.fill(prices, 99);
// 打印整型数组的所有元素数值
for (int price : prices) {
System.out.println("price = "+price);
}

  

3、Arrays.copyOf方法
把一个数组变量赋值给另一个数组变量,似乎可以用等号直接赋值,这种情况在一般情况下没有问题。但若是赋值之后修改了原数组的某个元素,那就出现问题了。譬如以下的演示代码,先把数组变量pricesOrigin赋值给pricesAssign,接着修改原数组pricesOrigin的元素值,再去打印新数组pricesAssign的所有元素:

		// 声明一个整型数组,数组大小为5,并且5个元素全为99
int[] pricesOrigin = {99, 99, 99, 99, 99};
// 复制数组的第一个办法:利用等号直接赋值
int[] pricesAssign = pricesOrigin;
pricesOrigin[1] = 80;
for (int price : pricesAssign) {
System.out.println("assign price = "+price);
}

运行以上的演示代码,完整的日志输出如下所示:

assign price = 99
assign price = 80
assign price = 99
assign price = 99
assign price = 99

没想到打印出来的第二个数组元素竟然变了,可是演示代码明明只改了原数组pricesOrigin,并未修改新数组pricesAssign呀。让测试程序出现神经错乱的缘故,乃是数组之间的等号赋值相当于给数组起个别名,并非从头到尾完整复制一个新数组出来。既然只是起了个别的名称,那么实际上还是原名称所指的数组,无非是该数组有两个姓名罢了。
显然这个情况不是程序员期望的结果,程序员的本意是复制另外的数组,新数组不再与原数组有任何关联,大家井水不犯河水,互不干涉、互不影响。最好克隆一个一模一样的新数组出来,Java恰巧给每个数组变量都提供了clone方法,该方法正是拿来克隆数组用的。克隆出来的新数组有分配单独的存储空间,并且数组元素的数值与原数组完全一致,如此便实现了正常意义上的数组赋值功能。利用clone方法复制数组变量的示例代码如下:

		// 复制数组的第二个办法:调用原数组的clone方法
int[] pricesClone = pricesOrigin.clone();
pricesOrigin[1] = 80;
for (int price : pricesClone) {
System.out.println("clone price = "+price);
}

运行如上的示例代码,得到下面的日志输出结果:

clone price = 99
clone price = 99
clone price = 99
clone price = 99
clone price = 99

可见此时修改了原数组的元素数值,并没有改变新数组的元素值,真正做到了完整的复制操作。
不过clone方法人如其名,它把原数组的所有元素一个不漏全部复制到新数组,这意味着,如果只想复制部分元素给新数组,那末clone方法就无能为力了。为此,Java给Arrays工具增配了一个copyOf方法,该方法允许从来源数组复制若干元素给目标数组。当待复制的元素个数恰好等于原数组的大小时,copyOf方法的作用等同于数组变量的clone方法。下面是通过copyOf方法将数组原样复制到新数组的代码例子:

		// 复制数组的第三个办法:调用Arrays工具的copyOf方法
int[] pricesCopy = Arrays.copyOf(pricesOrigin, pricesOrigin.length);
pricesOrigin[1] = 80;
for (int price : pricesCopy) {
System.out.println("copy price = "+price);
}

从上面代码看到,copyOf方法身后跟着两个参数,第一个参数是原数组的名称,第二个参数是要复制的元素个数。接下来把第二个参数改小一点,看看copyOf方法是否真的支持只复制部分元素?于是第二个参数改为“pricesOrigin.length-1”之后的代码如下所示:

		// 改变copyOf方法的第二个参数值,允许复制指定大小的数组元素
int[] pricesPart = Arrays.copyOf(pricesOrigin, pricesOrigin.length-1);
for (int price : pricesPart) {
System.out.println("part price = "+price);
}

重新运行修改后的数组复制代码,日志输出结果见下:

part price = 99
part price = 99
part price = 99
part price = 99

这下看到新数组的元素只有四个,而原数组共有五个元素,说明此时的确只复制了部分元素。
Arrays工具的copyOf方法还有个妙用,比如有个数组分配了初始大小为5,现在想把该数组的长度扩大到10,这时利用copyOf方法就能动态调整数组的大小。具体做法是:调用copyOf方法之时,来源数组和目标数组都填该数组的名称,然后待复制的元素大小填写扩大后的长度。下面的代码便演示了如何将某数组的大小拉长一位:

		// 把copyOf方法的返回值赋给原数组,可以动态调整该数组的大小
pricesOrigin = Arrays.copyOf(pricesOrigin, pricesOrigin.length+1);
for (int price : pricesOrigin) {
System.out.println("origin price = "+price);
}

运行调整数组大小的演示代码,观察到以下的日志输出:

origin price = 99
origin price = 99
origin price = 99
origin price = 99
origin price = 99
origin price = 0

由此可见,数组大小果然增大了一位,并且新增的数组元素值为0,这正是整型变量的默认数值。

4、Arrays.sort方法
顾名思义,Arrays工具的sort方法是给数组元素排序的,并且排序结果为升序。sort方法用起来很简单,只要把待排序的数组名称填进圆括号,编译器就会自动完成该数组的排序任务。举个给整型数组排序的例子,简单的Java实现代码如下:

		int[] pricesOrigin = {99, 80, 18, 68, 8};
// 对整型数组pricesOrigin里的元素进行排序操作,sort方法得到的结果是升序排列
Arrays.sort(pricesOrigin);
for (int price : pricesOrigin) {
System.out.println("origin price = "+price);
}

运行上述的排序代码,得到下面的结果日志:

origin price = 8
origin price = 18
origin price = 68
origin price = 80
origin price = 99

从日志看到,排序后的数组元素从小到大打印,很明显这是升序排列。
当然,在前面的例子中,数组元素早在声明数组时便初始化赋值了,实战性不强。接下来尝试动态生成一个随机数数组,再对该数组进行排序,这样更贴近实际业务。详细的实现代码可能涉及到数组、循环、冒号跳转等技术,有兴趣的朋友不妨动手实践。下面是随机数组生成并排序的代码例子:

		int[] numbers = new int[20];
loop : for (int i=0; i<numbers.length; i++) {
// 生成一个小于100的随机整数
int item = (int) Math.round(Math.random()*1000%100);
// 下面的循环用来检查数组中是否已经存在该随机数
for (int j=0; j<i; j++) {
if (numbers[j] == item) {
i--;
// 已经存在该随机数,则继续第一层循环,重新生成随机数
continue loop;
}
}
// 原数组不存在该随机数,则把随机数加入到数组中
numbers[i] = item;
}
// 对整型数组numbers里的元素进行排序操作,sort方法得到的结果是升序排列
Arrays.sort(numbers);
for (int number : numbers) {
System.out.println("number = "+number);
}

 

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(二十三)数组工具Arrays的更多相关文章

  1. Java开发笔记(十三)利用关系运算符比较大小

    前面在<Java开发笔记(九)赋值运算符及其演化>中提到,Java编程中的等号“=”表示赋值操作,并非数学上的等式涵义.Java通过等式符号“==”表示左右两边相等,对应数学的等号“=”: ...

  2. Java 学习笔记 二维数组和对象数组

    定义二维数组 int[][] a = new int[4][5]; 可以不指定列数 int[][] a = new int[4][]; 获取行 int i = a.length(); 如果使用第一个例 ...

  3. Java开发学习(二十三)----SpringMVC入门案例、工作流程解析及设置bean加载控制

    一.SpringMVC概述 SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装.SpringMVC是处于Web层的框架,所以其主要的作用就是用来 ...

  4. Java学习笔记二十三:Java的继承初始化顺序

    Java的继承初始化顺序 当使用继承这个特性时,程序是如何执行的: 继承的初始化顺序 1.初始化父类再初始子类 2.先执行初始化对象中属性,再执行构造方法中的初始化 当使用继承这个特性时,程序是如何执 ...

  5. Java开发笔记(序)章节目录

    现将本博客的Java学习文章整理成以下笔记目录,方便查阅. 第一章 初识JavaJava开发笔记(一)第一个Java程序Java开发笔记(二)Java工程的帝国区划Java开发笔记(三)Java帝国的 ...

  6. Java开发学习(二十五)----使用PostMan完成不同类型参数传递

    一.请求参数 请求路径设置好后,只要确保页面发送请求地址和后台Controller类中配置的路径一致,就可以接收到前端的请求,接收到请求后,如何接收页面传递的参数? 关于请求参数的传递与接收是和请求方 ...

  7. Java开发学习(二十四)----SpringMVC设置请求映射路径

    一.环境准备 创建一个Web的Maven项目 参考Java开发学习(二十三)----SpringMVC入门案例.工作流程解析及设置bean加载控制中环境准备 pom.xml添加Spring依赖 < ...

  8. Java开发学习(二十六)----SpringMVC返回响应结果

    SpringMVC接收到请求和数据后,进行了一些处理,当然这个处理可以是转发给Service,Service层再调用Dao层完成的,不管怎样,处理完以后,都需要将结果告知给用户. 比如:根据用户ID查 ...

  9. Java开发学习(二十七)----SpringMVC之Rest风格解析及快速开发

    一.REST简介 REST(Representational State Transfer),表现形式状态转换,它是一种软件架构风格 当我们想表示一个网络资源的时候,可以使用两种方式: 传统风格资源描 ...

  10. Java开发学习(二十八)----拦截器(Interceptor)详细解析

    一.拦截器概念 讲解拦截器的概念之前,我们先看一张图: (1)浏览器发送一个请求会先到Tomcat的web服务器 (2)Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源 (3)如 ...

随机推荐

  1. 我的第一次做app的细节

    第一次做一个app 发现 需要和前端沟通好而且 还要注意细节  效果图细节不要忘记 尽量多穿数据不要少传数据 而且 对接 注意细节

  2. django 利用pillow 进行简单的设置验证码(python)

    1.导入模块 并定义一个验证状态 from PIL import Image, ImageDraw, ImageFont from django.utils.six import BytesIO de ...

  3. 梯度提升决策树(GBDT)

    1.提升树 以决策树为基函数的提升方法称为提升树.决策树可以分为分类树和回归树.提升树模型可以表示为决策树的加法模型. 针对不同的问题的提升术算法的主要区别就是损失函数的不同,对于回归问题我们选用平方 ...

  4. Python爬虫6-利用ProxyHandler设置代理服务器

    GitHub代码练习地址:https://github.com/Neo-ML/PythonPractice/blob/master/SpiderPrac09_ProxyHandler.pyProxyH ...

  5. 【从零开始搭建自己的.NET Core Api框架】(一)创建项目并集成swagger:1.1 创建

    系列目录 一.  创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...

  6. [Swift]LeetCode633. 平方数之和 | Sum of Square Numbers

    Given a non-negative integer c, your task is to decide whether there're two integers a and b such th ...

  7. Redis 设计与实现 (五)--多机数据库的实现

    多机数据库的实现 一.复制 slaveof  主服务器ip地址.形成主从关系. 1.同步  从向主服务器发送sync命令.  主服务器收到sync命令执行bgsave,生成rdb文件,缓冲区同时记录从 ...

  8. FAutoTest-微信小程序 / 公众号H5 自动化利器

    X5内核H5自动化背景 近来有很多童靴咨询如何做微信小程序/公众号等H5页面来做自动化,之前写了一篇文章微信小程序自动化测试实践 https://www.cnblogs.com/yyoba/p/945 ...

  9. iOS学习——Quartz2D学习之DrawRect

    Quartz2D学习之DrawRect 本文以问答形式主要讲述Quartz2D的相关内容,参考内容是网上下载的学习视频资料. 1.什么是Quartz2D? 他是一个二维的绘图引擎,同时支持iOS和Ma ...

  10. Python内置函数(45)——object

    英文文档: class objectReturn a new featureless object. object is a base for all classes. It has the meth ...