Java数组操作利器:Arrays工具类
java.util.Arrays提供大量的工具方法来操作数组,这些方法全是静态方法。
1 便捷创建List
public static <T> List<T> asList(T... a)
返回一个受指定数组支持的固定大小的列表。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
典型用法:List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
2 二分查找
有多个重载的方法。比如,
public static int binarySearch(long[] a,long key)
public static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key)
public static <T> int binarySearch(T[] a,int fromIndex,int toIndex,T key,Comparator<? super T> c)
二分查找要求数组是有序的,并且数组中的元素是可以比较大小的。
3 复制数组
有多个重载的版本。
(1)public static <T> T[] copyOf(T[] original, int newLength)
复制指定的数组,截取或用 null 填充(如有必要),以使副本具有指定的长度。这个方法会把original数组复制成一个新数组,其中length是新数组的长度。如果length小于original数组的长度,则新数组就是原数组的前面length个元素,如果length大于original数组的长度,则新数组就是原数组的所有元素,后面补充0,false或者null。
(2)public static <T> T[] copyOfRange(T[] original, int from, int to)
与上面的方法类似,只是这个方法只复制original数组的from索引到to索引的元素。
System.arraycopy方法
System类的arraycopy方法签名如下:
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
Arrays类中所有复制数组的方法底层都是调用System.arraycopy方法,这是一个本地静态方法。对于基本类型数组,该方法实现了深复制;然而对于对象数组而言,System.arraycopy方法只是浅复制。也就是说这个方法只是将原来的数组对象本身复制一份,并没有将该数组中各个数据元素所指向的对象复制一份。也就是说,新的数组中的各个数组元素仍然和原数组中的各个元素指向的是同一个对象。这样的话就会产生一个问题:修改新数组中的某个数组元素所指向的对象的属性的话,那么以前的那个数组对应的数组元素的对象也被修改了。
看例子:
import java.util.Arrays; class Student {
private static int count = 1000;
private int id = count++;
private String name = "No." + id; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
} } public class ArraycopyTest { public static void main(String[] args) { Student[] old = new Student[] { new Student(), new Student(),
new Student(), };
Student[] fresh = new Student[5]; System.arraycopy(old, 0, fresh, 0, old.length); System.out.println(" old:" + Arrays.toString(old));
System.out.println("fresh:" + Arrays.toString(fresh)); fresh[2].setName("Obama");
fresh[2].setId(9999); System.out.println(" old:" + Arrays.toString(old));
System.out.println("fresh:" + Arrays.toString(fresh));
}
}
输出结果:
old:[Student [id=1000, name=No.1000], Student [id=1001, name=No.1001], Student [id=1002, name=No.1002]]
fresh:[Student [id=1000, name=No.1000], Student [id=1001, name=No.1001], Student [id=1002, name=No.1002], null, null]
old:[Student [id=1000, name=No.1000], Student [id=1001, name=No.1001], Student [id=9999, name=Obama]]
fresh:[Student [id=1000, name=No.1000], Student [id=1001, name=No.1001], Student [id=9999, name=Obama], null, null]
程序本来是想修改fresh数组的fresh[2]中的Student的信息,结果old数组中的对应的Student的信息也被修改了。
先看看内存图,这是程序执行fresh[2].setName("Obama");fresh[2].setId(9999);两行代码之前的内存布局:
下面是程序执行fresh[2].setName("Obama");fresh[2].setId(9999);两行代码之后的内存布局:
原因很显然,不多说了。
补充资料:Object中的clone方法
Object中的clone方法也与System.arraycopy类似,clone是一个protected方法。如果对象中的所有数据域都属于数值或者基本类型,这样的拷贝没有问题。但是如果在对象中包含了子对象的引用,拷贝的结果会使得两个域引用指向同一个子对象,因此原始对象和克隆对象共享这部分信息。也就是说,默认的clone操作是浅拷贝,它没有克隆包含在对象中的内部对象。
由于clone方法被声明为protected,所以只有子类能调用受保护的clone方法克隆它自己。其他对象不能调用某个对象的clone方法。
解决方案:重新定义clone方法,并将它声明为public,并实现一个标记接口Cloneable,告诉其他对象可以调用该类的clone方法。
比如可以对上述的Student类重写如下clone方法:
@Override
public Student clone() throws CloneNotSupportedException{
Student cloned = (Student)super.clone();
cloned.name = new String(name); //对于非基本类型的数据域要重新赋值
return cloned;
}
4 打印数组元素
public static String toString(Object[] a)
返回指定数组内容的字符串表示形式。形如[element[0].toString,element[1].toString,...]
public static String deepToString(Object[] a)
此方法是为了将多维数组转换为字符串而设计的。
5 两个数组是否相等
public static boolean equals(Object[] a,Object[] a2)
如果两个指定的 Objects 数组彼此相等,则返回 true。如果两个数组包含相同数量的元素,并且两个数组中的所有相应元素对都是相等的,则认为这两个数组是相等的。如果 (e1==null ? e2==null : e1.equals(e2)),则认为 e1 和 e2 这两个对象是相等的 。换句话说,如果两个数组以相同顺序包含相同的元素,则两个数组是相等的。此外,如果两个数组引用都为 null,则认为它们是相等的。
public static boolean deepEquals(Object[] a1, Object[] a2)
如果两个指定数组彼此是深层相等 的,则返回 true。此方法适用于任意深度的嵌套数组。
6 哈希值
public static int hashCode(Object[] a)
基于指定数组的内容返回哈希码。这个哈希码有数组元素的哈希码组成。
public static int deepHashCode(Object[] a)
基于指定数组的“深层内容”返回哈希码。
7 数组赋值
public static void fill(Object[] a, Object val)
将数组的所有数组元素取值设置为val。
8 排序
public static void sort(short[] a)
根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。
public static <T> void sort(T[] a,Comparator<? super T> c)
根据指定比较器产生的顺序对指定对象数组进行排序。
Java数组操作利器:Arrays工具类的更多相关文章
- Java:集合,Arrays工具类用法
1. 描述 Arrays工具类提供了针对数组(Array)的一些操作,比如排序.搜索.将数组(Array)转换列表(List)等等,都为静态(static)方法: binarySearch - 使用二 ...
- Java集合框架:Arrays工具类
java.util.Arrays类能方便地操作数组,它提供的方法都是静态的.整个Arrays工具类的实现有3000+行.可是归纳总结一下可知它有下面功能(9个): 1. asList 定义: @Saf ...
- java之操作集合的工具类--Collections
Collections是一个操作Set.List和Map等集合的工具类. Collections中提供了大量方法对集合元素进行排序.查询和修改等操作,还提供了对集合对象设置不可变.对集合对象实现同步控 ...
- 二维数组及Arrays工具类
1.二维数组 概念: 数组中的每一个元素类型都是一维数组 二维数组初始化方式: 静态初始化: 格式: 元素类型[][] 数组名 = new 元素类型[][]{{一维数组1},{一维数组2},{一维数组 ...
- java中的数组的Arrays工具类的使用
package day04.d1.shuzu; import java.util.Arrays; /** * Arrays 工具类 * @author Administrator * */public ...
- java 13-2 Arrays工具类
1.Arrays:针对数组进行操作的工具类.比如说排序和查找. 1:public static String toString(int[] a) 把数组转成字符串 2:public static v ...
- Java基础知识强化62:Arrays工具类之概述和使用
1. Arrays工具类: Arrays这个类包含操作数组(比如排序和查找)的各种方法. 2. Arrays的方法: (1)toString方法:把数组转成字符串 public static Stri ...
- Java精选笔记_集合概述(Collection接口、Collections工具类、Arrays工具类)
集合概述 集合有时又称为容器,简单地说,它是一个对象,能将具有相同性质的多个元素汇聚成一个整体.集合被用于存储.获取.操纵和传输聚合的数据. 使用集合的技巧 看到Array就是数组结构,有角标,查询速 ...
- java数据结构1--数组、排序和Arrays工具类
数组:Array 数组的定义 数组的内存结构 数组定义常见问题 数组常见操作 Java参数传递问题--值传递 二维数组 1.数组概念 同一种类型数据的集合,可以是基本数据类型,也可以是引用数据类型. ...
随机推荐
- BZOJ4197[NOI2005]寿司晚宴
Description 为了庆祝 NOI 的成功开幕,主办方为大家准备了一场寿司晚宴.小 G 和小 W 作为参加 NOI 的选手,也被邀请参加了寿司晚宴. 在晚宴上,主办方为大家提供了 n−1 种不同 ...
- PhpExcel中文帮助手册|PhpExcel使用方法
下面是总结的几个使用方法 include 'PHPExcel.php'; include 'PHPExcel/Writer/Excel2007.php'; //或者include 'PHPExcel/ ...
- 在Java代码中使用pdfBox将PDF转换为图片
生成图片 // 生成图片 PDDocument pd = PDDocument.load(new File(filePath)); PDFRenderer pdfRenderer = new PDFR ...
- PL/SQL流程控制语句
PL/SQL流程控制语句介绍PL/SQL的流程控制语句, 包括如下三类:控制语句: IF 语句循环语句: LOOP语句, EXIT语句顺序语句: GOTO语句, NULL语句①if语句 IF < ...
- 十个节省时间的MySQL命令
十个节省时间的MySQL命令 2011-02-23 16:07 黄永兵 译 IT168 字号:T | T 编者在工作中积累起来了一些MySQL命令行客户端技巧,这些技巧或多或少会帮助您节省大量的时间. ...
- Wcf:可配置的服务调用方式
添加wcf服务引用时,vs.net本来就会帮我们在app.config/web.config里生成各种配置,这没啥好研究的,但本文谈到的配置并不是这个.先看下面的图: 通常,如果采用.NET的WCF技 ...
- Redirect和Dispatcher 区别
使用forward是服务跳转,浏览器不知道它所请求的具体资源来源,浏览器的地址栏不会变:使用redirect,服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL ...
- 如何用 fiddler 代理调试本地手机页面
最近在做移动端的页面,但是移动端的调试很蛋疼.虽然说 90% 的功能都能用 chrome 下的模拟器来模拟解决,但是剩余的 10% 却只能在真机上调试.比如说一两个像素的误差,比如说只有真机上才能重现 ...
- word-wrap,word-break和white-space总结
最近网页布局中遇到得比较多,所以打算总结总结. word-wrap: 1.normal(使用浏览器默认的换行规则) 2.break-word(内容将在边界内换行,但是英文换行会按词断句) word-b ...
- 你是否还在质疑EF的性能
1. 写在前面的话 一直没有写博客的习惯,感觉太浪费时间,没有那么多精力,其实仔细一想,写博客是一种习惯,也是一种心境,同时也是对自己所掌握的知识结构的一个梳理过程,对自己知识体系的一个巩固,同时也是 ...