• Arrays工具类主要是方便数组操作的,学习好该类可以让我们在编程过程中轻松解决数组相关的问题,简化代码的开发。
  • Arrays类有一个私有的构造函数,没有对外提供实例化的方法,因此无法实例化对象。因为该类是个工具类,因此使用的时候主要使用静态方法。
  • 由于数组里面可包含的对象类型很多,比如int、long、float等等,因此Arrays的静态方法有很多重载的方法。我们在学习研究的过程中只需要针对一种类型研究透即可。

由于Arrays的方法很多,这一章我们主要从简单的方法进行分析。

toString方法


使用方式:

Arrays工具类的toString方法,主要将数组转换为字符串。这在我们打印数组内容的时候非常有用。

   public static void main(String[] args) {
int[] a = {9, 9, 9, 9, 9};
int[] b = null;
int[] c = new int[10];
int[] d = {}; System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
System.out.println(Arrays.toString(c));
System.out.println(Arrays.toString(d));
}

返回结果如下:

[9, 9, 9, 9, 9]
null
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[]

源码分析

我们只分析一种类型的,比如整型,其余类型的代码大体类似。注意该方法没有对原有数组进行改变,只是新产生了一个包含数组内容的字符串。

   public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]"; StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
  • 如果数组为null,则返回 null 字符串

  • 用一个变量 iMax 存储数组长度减一的值。此值如果为 -1,表示 数组长度为0,那么就返回字符串 [].

  • 使用StringBuilder合并字符串,遍历数组,组装字符串。并且使用[]括起来。

fill方法


Arrays工具类的fill方法,主要将数组进行填充。比如我们新建了一个数组,之后想对其元素全部初始化为100,这个时候使用for循环进行赋值则显得麻烦,直接使用工具方法便可完成此功能。

使用方式一

   public static void main(String[] args) {
int[] a = {9, 9, 9, 9, 9};
Arrays.fill(a, 1);//全部置为1,将原有的9覆盖
int[] c = new int[10];
Arrays.fill(c, 3);//全部置为3,类似与赋值
int[] d = {};
Arrays.fill(d, 4);//无意义 System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(c));
System.out.println(Arrays.toString(d));
}

返回结果如下:

[1, 1, 1, 1, 1]
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
[]

从上面的使用方式来看,这个方法最适合新建一个数组之后,给数组赋值一个初始值,并且这个初始值并不是各个类型默认的值,如0之类的。

源码分析:非常简单,遍历赋值。

    public static void fill(int[] a, int val) {
for (int i = 0, len = a.length; i < len; i++)
a[i] = val;
}

使用方式二

对数组的部分元素填充一个值,从起始位置到结束位置,取头不取尾

    public static void main(String[] args) {
int[] a = {9, 9, 9, 9, 9};
Arrays.fill(a, 1, 3, 4);
//[9, 4, 4, 9, 9]
System.out.println(Arrays.toString(a));
}

源码分析:这种部分赋值的方法注意需要记住方法里面的参数的含义即可,通过源码可以清楚看出:

    public static void fill(int[] a, int fromIndex, int toIndex, int val) {
rangeCheck(a.length, fromIndex, toIndex);
for (int i = fromIndex; i < toIndex; i++)
a[i] = val;
}
  • 第一个参数是待填充的数组
  • 第二个参数是待填充数组的起始索引位置(包含)
  • 第三个参数是待填充数组的结束索引位置(不包含)
  • 第四个参数是要填充的数值

下面是参数校验的功能:

   private static void rangeCheck(int arrayLength, int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IllegalArgumentException(
"fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
}
if (fromIndex < 0) {
throw new ArrayIndexOutOfBoundsException(fromIndex);
}
if (toIndex > arrayLength) {
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}

copyOf方法


使用方式

copyOf方法的功能是拷贝一个数组。它内部是使用了System.arraycopy方法进行拷贝。首先看下使用方式。

public static void main(String[] args) {
int[] a = {1, 2};
System.out.println(Arrays.toString(a)); //[1, 2] int[] b = Arrays.copyOf(a, 0);
System.out.println(Arrays.toString(b)); //[] int[] c = Arrays.copyOf(a, 1);
System.out.println(Arrays.toString(c)); //[1] int[] d = Arrays.copyOf(a, 2); //实际可用a.length替代2
System.out.println(Arrays.toString(d)); //[1, 2] int[] e = Arrays.copyOf(a, 3);
System.out.println(Arrays.toString(e)); //[1, 2, 0]
}

源码分析:

   public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}

该方法需要一个原数组和一个需要生成新数组的长度这两个参数。

  • 首先生成一个新数组,使用指定的长度。
  • 调用System.arraycopy方法进行生成新的数组。

注意 Math.min(original.length, newLength) 的含义是,如果传入的长度大于原数组的长度,则使用原数组的长度,否则使用新传入的数组长度。

System.arraycopy介绍

    /*
* @param src 原数组.
* @param srcPos 从元数据的起始位置开始.
* @param dest 目标数组.
* @param destPos 目标数组的开始起止位置.
* @param length 要拷贝的数组长度.
* @exception IndexOutOfBoundsException if copying would cause
* access of data outside array bounds.
* @exception ArrayStoreException if an element in the <code>src</code>
* array could not be stored into the <code>dest</code> array
* because of a type mismatch.
* @exception NullPointerException if either <code>src</code> or
* <code>dest</code> is <code>null</code>.
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);

示例:

    public static void main(String[] args) {
int[] x = {1, 2, 3, 4, 5, 6, 7};
int[] y = {11, 12, 13, 14, 15, 16, 17};
System.arraycopy(x, 1, y, 1, 5);
System.out.println(Arrays.toString(x));//[1, 2, 3, 4, 5, 6, 7]
System.out.println(Arrays.toString(y));//[11, 2, 3, 4, 5, 6, 17]
}

System.arraycopy(x, 1, y, 1, 5); 这句的含义是:

将x数组从第二个位置起拿出5个元素,放置到y数组的第二个位置及以后。

copyOfRange方法


copyOfRange方法同样也是拷贝一个数组,只是拷贝的时候需要指定起始位置和结束位置。而copyOf只能传递拷贝的元素的个数,并且是从原数组的第一个元数开始拷贝。

使用方式:

    public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5, 6};
System.out.println(Arrays.toString(a)); //[1, 2, 3, 4, 5, 6] int[] b = Arrays.copyOfRange(a, 1, 4);
System.out.println(Arrays.toString(b)); //[2, 3, 4] int[] c = Arrays.copyOfRange(a, 1, 10);
System.out.println(Arrays.toString(c)); //[2, 3, 4, 5, 6, 0, 0, 0, 0]
}

源码分析:

    public static int[] copyOfRange(int[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
int[] copy = new int[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}

首先判断开始位置和结束位置是否合理,不合理就报错,然后和copyOf源码一样,,使用System.arraycopy方法进行生成新的数组。

关于copyOfRange和copyOf拷贝对象,本节不做介绍,后面会仔细分析。

Arrays工具类使用与源码分析(1)的更多相关文章

  1. Java基础知识强化63:Arrays工具类之方法源码解析

    1. Arrays工具类的sort方法: public static void sort(int[] a): 底层是快速排序,知道就可以了,用空看. 2. Arrays工具类的toString方法底层 ...

  2. Django——基于类的视图源码分析 二

    源码分析 抽象类和常用视图(base.py) 这个文件包含视图的顶级抽象类(View),基于模板的工具类(TemplateResponseMixin),模板视图(TemplateView)和重定向视图 ...

  3. netty中的发动机--EventLoop及其实现类NioEventLoop的源码分析

    EventLoop 在之前介绍Bootstrap的初始化以及启动过程时,我们多次接触了NioEventLoopGroup这个类,关于这个类的理解,还需要了解netty的线程模型.NioEventLoo ...

  4. DAO工具类的封装源码

    详细源码见下表,绝对原创,转载请注明出处! package com.ydj.util; import java.sql.Connection; import java.sql.PreparedStat ...

  5. Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析

    目录 0.前言 1.TemporalAccessor源码 2.Temporal源码 3.TemporalAdjuster源码 4.ChronoLocalDate源码 5.LocalDate源码 6.总 ...

  6. Django——基于类的视图源码分析 一

    基于类的视图(Class-based view)是Django 1.3引入的新的视图编写方式,用于取代以前基于函数(Function-based)方式. 借助于OO和Python中方便的多重继承特性, ...

  7. Django——基于类的视图源码分析 三

    列表类通用视图(list.py) 此文件包含用于显示数据列表常用的类和工具类.不仅可以方便的用于显示基于模型(Model)的数据列表,也可以用于显示自定义数据列表. 此图中绿色部分属于base.py, ...

  8. java String类 trim() 方法源码分析

    public String trim() {        int arg0 = this.value.length;   //得到此字符串的长度        int arg1 = 0;   //声 ...

  9. jQuery-1.9.1源码分析系列完毕目录整理

    jQuery 1.9.1源码分析已经完毕.目录如下 jQuery-1.9.1源码分析系列(一)整体架构 jQuery-1.9.1源码分析系列(一)整体架构续 jQuery-1.9.1源码分析系列(二) ...

随机推荐

  1. Waiting for table flush 阻塞查询的问题

    1.此状态表示大量thread正在等待慢查询语句执行完成. 原因: The thread got a notification that the underlying structure for a ...

  2. 解决Vscode编辑器不能打开多标签页问题

    问题描述:编辑代码时,初用vscode,不能打开多个文件:每打开一个文件,都会替换前面一个文件标签,很不方便切换编码: 想要的效果: 解决方式: 方法一: 找到setting.json文件,最外层花括 ...

  3. [译]深度学习(Yann LeCun)

    深度学习 严恩·乐库  约书亚•本吉奥  杰弗里·希尔顿 摘要深度学习是计算模型,是由多个处理层学习多层次抽象表示的数据.这些方法极大地提高了语音识别.视觉识别.物体识别.目标检测和许多其他领域如药物 ...

  4. Oracle Set操作

    并集合 union/uinon all union 会去重,uinon all 不去重 交集 intersect 差集 minus

  5. 实现memcpy()函数及过程总结

    1.为什么会写memcpy 在之前的应聘笔试上遇到一道笔试题,题目要求实现一个my_memcpy函数.函数原型:void * my_memcpy(void *dst, const void *src, ...

  6. 【串线篇】spring boot配置文件加载位置

    springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件 (1)–file:./config/ ...

  7. Java常用类库API之数字处理工具类

    数字处理工具类BigDecimal和DecimalFormat Java提供的java.text.DecimalFormat类,帮助我们用最快的速度将数据格式化为我们想要的样子.例如,取两位小数 im ...

  8. django权限之二级菜单

    遗漏知识点 1.构建表结构时,谁被关联谁就是主表,在层级删除的时候,删除子表的时候,主表不会被删除,反之删除主表的话,字表也会被删除, 使用related_name=None   反向查询,起名用的 ...

  9. 对http的研究

    HTTP 简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准. HTTP是一个基于 ...

  10. 【HDOJ6659】Acesrc and Good Numbers(dfs)

    题意:定义f(n,d)为数码d在1到n中出现的次数,其中d=0..9 如果f(d,k)=k,则称k是d好数 给定x和d,求不大于x的最大的d好数 x<=1e18 思路:考虑f的增长率主要和位数有 ...