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)
根据指定比较器产生的顺序对指定对象数组进行排序。

时间: 2024-10-18 14:17:02

Java数组操作利器:Arrays工具类的相关文章

java 13-2 Arrays工具类

1.Arrays:针对数组进行操作的工具类.比如说排序和查找. 1:public static String toString(int[] a) 把数组转成字符串  2:public static void sort(int[] a) 对数组进行排序  3:public static int binarySearch(int[] a,int key) 二分查找 1 import java.util.Arrays; //通过API查找,并不属于long包,所以需要导包 2 public class

Java连载71-二分查找和Arrays工具类

一.二分法查找 1.二分法查找是建立在已经排序的基础之上的 2.程序分析是从下到大?排序. 3.这个数组中没有重复的元素?. package com.bjpowernode.java_learning; ? public class D71_1_ { public static void main(String[] args) { int[] a1 = {1,5,8,9,11,25,45,55}; int destElement = 29; int index = binarySearch(a1

在Java中Arrays工具类实现功能的六种方法

使用Arrays工具类,要先导入包即:import.java.util.Arrays 以下是实现六种功能的方法: 1.比较两个数组值是否相等: 结果为true.false.(布尔型不能比较) int []a={10,20,30}; int []b={10,20,30}; int []c={1,2,3}; boolean isEqual=Arrays.equals(a,b); System.out.println(isEqual); System.out.println(Arrays.equals

Java基础知识强化之集合框架笔记33:Arrays工具类中asList()方法的使用

1. Arrays工具类中asList()方法的使用 1 public static <T> List<T> asList(T... a): 把数组转成集合 注意事项: 虽然可以把数组转成集合,但是集合的长度不能改变. 2. 代码示例: (1) 1 package cn.itcast_03; 2 3 import java.util.Arrays; 4 import java.util.List; 5 6 /* 7 * public static <T> List<

JAVA基础——Arrays工具类十大常用方法

Arrays工具类十大常用方法 原文链接:http://blog.csdn.net/renfufei/article/details/16829457 0. 声明数组 String[] aArray = new String[5]; String[] bArray = {"a","b","c", "d", "e"}; String[] cArray = new String[]{"a",

Arrays工具类

Arraysd的静态方法能够方便的对数组进行操作,每个方法也加了注释 : 程序: import java.util.*;public class Array{        public static void main(String[] args){                int[]  arr={1,3,4,2};                System.out.println("排序前:");                printArray(arr);//打印原数组

黑马程序员——19,Collections工具类,Arrays工具类,高级for循环,可变参数,静态导入

------<ahref="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------- 黑马程序员--19,Collections工具类,Arrays工具类 /* Collections是一个类,注意,这里后面带有一个s 千万不要和Collection弄混了!Collection只是接口而已. 两者要区别开来. Collect

Collections 工具类和 Arrays 工具类常见方法

Collections 工具类和 Arrays 工具类常见方法 Collections Collections 工具类常用方法: 排序 查找,替换操作 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合) 排序操作 void reverse(List list)//反转 void shuffle(List list)//随机排序 void sort(List list)//按自然排序的升序排序 void sort(List list, Comparator c)//定制

7.8 操作集合的工具类:Collections

目录 一.排序操作 二.查找和替换功能 三.同步控制 四.设置不可变集合 五.Java 9新增的不可变集合 一.排序操作 Collections提供了如下常用类方法用于对List集合进行排序: ★void reverse(List list):反转指定的List集合中的元素顺序. ★void shuffle(List list):对Lsit集合中的元素进行随机排序(shuffle方法模仿了"洗牌"动作). ★void sort(List list):根据元素的自然顺序对指定集合元素按升