Arrays类

简介: 为了简化对数组的操作,JDK1.2在`java.util`包下增加了一个Arrays类(数组工具类),里面提供了一系列静态方法,用于对数组进行排序、查找等。Arrays类常见方法如表所示。

@toc

1、Arrays类

  为了简化对数组的操作,JDK1.2在java.util包下增加了一个Arrays类(数组工具类),里面提供了一系列静态方法,用于对数组进行排序、查找等。Arrays类常见方法如表所示。

序号 方法定义 描述
1 String toString(int[] arr) 将数组各元素进行拼接,最终返回数组格式的字符串
2 void sort(int[] arr) 对指定的int型数组按数字升序进行排序
3 void sort(Object[] a) 根据元素的自然顺序对指定对象数组按升序进行排序
4 void sort(Object[] a,Comparator c) 根据指定比较器产生的顺序对指定对象数组进行排序
5 int binarySearch(int[] arr.int key) 通过二分查找法,搜索有序的arr数组中是否存在key元素,返回索引,如果找不到则返回负数。如果数组无序,则结果不确定。
6 int binarySearch(Object[] a,Object key) 使用二分搜索法来搜索指定数组,以获得指定对象。在进行此调用之前,必须根据元素的自然顺序对数组进行升序排序(通过sort(Object[] obj)方法)。如果没有对数组进行升序排序,则结果是不确定的。
7 int binarySearch(Object[] a,Object key,Comparator c) 使用二分搜索法来搜索指定数组,以获得指定对象。在进行此调用之前,必须根据同一个比较器(通过sort(Object[] obj,Comparator c)方法)对数组进行升序排序。如果没有对数组进行排序,则结果是不确定的。
8 int[] copyOf(int[] original,int newLength) 赋值数组,返回的新数组长度是newLength
9 boolean equals(int[] a1,int[] a2) 判断两个数组的元素是否都相等
10 boolean equals(Object[] a,Object[] a2) 判断两个数组的元素是否都相等,依赖于元素的equals方法
  上述方法提供了多种重载形式,除了支持int[],还支持其他各种类型的数组,甚至也支持对象数组,这里就不再赘述了。

1.1 toString方法:转换字符串

  使用数组存储数据之后,查看所有数组元素是最基本的需求,之前我们不得不使用for循环进行遍历。有了Arrays类之后,可以使用Arrays的toString方法,快速地返回数组的所有元素内容。该方法返回的字符串格式为[元素1,元素2,...],该方法为重载方法,参数类型支持任意类型的数组。

import java.util.Arrays;

public class ToStringTest {
    public static void main(String[] args) {
        int[] arr={1,5,3,2,4};
        System.out.println(Arrays.toString(arr));
    }
}

image-20221007124027502

1.2 sort方法:自然排序

  对数组元素的排序可谓能难倒一堆初学者,但是如果不谈实现代码,仅从实现排序效果来说还是非常简单的。Arrays类提供了sort方法用于对各种类型的数组进行升序排序

  排序一般分为自然排序定制排序

  自然排序,是指基本数据类型的数组就是按照数值本身的大小进行排序;对象数组的自然排序就是元素本身已经实现java.lang.Comparable接口的compareTo方法,即对象本身具有了可比较性,所以在排序时,按着元素本身的比较规则(compareTo方法的实现)进行排序。该方法为重载方法,支持除boolean类型的任意类型元素。

  下面分别以常用的整型数组和对象数组类型为例,进行代码演示。

  案例1:整数数组的自然排序

import java.util.Arrays;

/**
 * 整数数组的自然排序
 */
public class ArraysSortTest1 {
    public static void main(String[] args) {
        int[] arr={5,2,1,4,3};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

image-20221007124544324

  案例2:对象数组的自然排序,以Person[]为例,当然需要先定义好Person类。

import java.util.Objects;

public class Person implements Comparable{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    //重写compareto方法-按年龄比较大小
    @Override
    public int compareTo(Object o) {
        Person p=(Person) o;
        return this.age-p.age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

  测试类示例代码:

import java.util.Arrays;

/**
 * 对象数组的自然排序
 */
public class ArraysSortTest2 {
    public static void main(String[] args) {
        Person[] pers={
                new Person("john",12),
                new Person("john1",23),
                new Person("john2",5),
                new Person("john3",20),
                new Person("john4",18),
        };
        Arrays.sort(pers);
        for (Person per : pers) {
            System.out.println(per);
        }
    }
}

image-20221007124706400

   如果Person类没有实现Comparable接口,则会抛出ClassCastException(类型转换异常),因为Arrays.sort方法底层会将Person元素进行转型,转换为Comparable接口类型然后调用compareTo方法。

  前面我们学习的八大包装类型、String类型都已经实现了Comparable接口,所以可以直接排序。

1.3 sort方法:定制排序

  定制排序,是指不管数组元素本身是否已经实现Comparable接口的compareTo方法,在排序时都是用定制比较器的比较规则进行排序。

  定制比较器是指java.util.Comparator接口的实现类对象,包含抽象方法int compare(Object obj1,Object obj2),定制排序器只支持对象数组。

  下面以Person[]为例进行演示,Person类是否实现Comparable接口并无要求,具体代码如下:

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  测试类示例代码:

import java.util.Arrays;
import java.util.Comparator;

/**
 * sort方法:定制排序
 */
public class ArraysSortTest3 {
    public static void main(String[] args) {
        Person[] pers={
                new Person("john",12),
                new Person("lily",23),
                new Person("lucy",5),
                new Person("jack",20),
                new Person("rose",18),
        };
        System.out.println("按照年龄排序:");
        Arrays.sort(pers, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });
        for (Person per : pers) {
            System.out.println(per);
        }

        System.out.println("按照姓名排序:");
        Arrays.sort(pers, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

        for (Person per : pers) {
            System.out.println(per);
        }
    }
}
   这块对Lambda表达式比较熟悉的话,可以重构一下上面的代码。

image-20221007125855999

  上述代码使用匿名内部类的方式实现了Comparator接口,使得代码更紧凑。

1.4 binarySearch:查找

  二分查找的效率远远高于顺序查找。Arrays类提供了二分查找的直接实现方法binarySearch,我们直接调用即可。当然该方法返回正确结果的前提是待查找的数组已经排好序,否则结果是不确定的。对象数组要求元素必须支持自然排序或指定了定制比较器对象。

  下面以整型数组为例,进行代码演示。

import java.util.Arrays;

public class BinarySearchTest {
    public static void main(String[] args) {
        int[] arr={1,3,5,7,9};
        System.out.println("5在数组中的下标:"+ Arrays.binarySearch(arr,5));
    }
}

image-20221007130433831

1.5 copyOf方法:数组复制

  数组扩容等操作通常都涉及数组的复制操作,Arrays类的copyOf方法和copyOfRange方法可以满足不同场合的排序。

  下面以常用的整型数组为例,进行代码演示。

import java.util.Arrays;

public class CopyOfTest {
    public static void main(String[] args) {
        int[] a={5,2,1,4,3};

        int[] newArr1= Arrays.copyOf(a,a.length-2);
        System.out.println("长度为原数组长度-2的新数组:"+Arrays.toString(newArr1));

        int[] newArr2= Arrays.copyOf(a,a.length+2);
        System.out.println("长度为原数组长度+2的新数组:"+Arrays.toString(newArr2));
    }
}

image-20221007130559922

1.6 equals方法:判断数组的元素是否相等

  如果需要比较两个数组的元素是否完全相等,那么可以直接使用Arrays类的equals方法来比较,该方法为重载方法,参数类型支持任意类型的数组。如果是基本数据类型,则直接比较数组的长度和元素值;如果是引用数据类型,则比较数组的长度及每个元素的equals方法。

  下面以对象数组为例,进行代码演示。

  Person类代码:

import java.util.Objects;

public class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

  测试类示例代码:

import java.util.Arrays;

/**
 * equals方法:判断数组元素是否相等
 */
public class ArraysEqualsTest {
    public static void main(String[] args) {
        Person[] arr1={
                new Person("john",12),
                new Person("lily",23),
                new Person("lucy",5),
                new Person("jack",20),
                new Person("rose",18),
        };
        Person[] arr2={
                new Person("john",12),
                new Person("lily",23),
                new Person("lucy",5),
                new Person("jack",20),
                new Person("rose",18),
        };
        System.out.println(Arrays.equals(arr1,arr2));
    }
}

image-20221007131010854

1.7 案例:左奇右偶

  案例需求:现在有一个长度为10的数组{26,67,49,38,52,66,7,71,56,87},先要求将所有的奇数放在数组的左侧,所有的偶数放在数组的右侧,并且把所有的奇数实现从小到大排列,所有的偶数也实现从小到大排列,结果如{7,49,67,71,87,26,38,52,56,66}。

import java.util.Arrays;
public class OddLeftEvenRight {
    public static void main(String[] args) {
        int[] arr={26,67,49,38,52,66,7,71,56,87};
        int left=0;
        int right=arr.length-1;
        while(left<right){
            while(arr[left]%2!=0){
                left++;
            }
            while(arr[right]%2==0){
                right--;
            }
            if(left<right){
                int temp=arr[left];
                arr[left]=arr[right];
                arr[right]=temp;
            }
        }
        Arrays.sort(arr,0,left);
        Arrays.sort(arr,right+1,arr.length);
        System.out.println(Arrays.toString(arr));
    }
}

image-20221007131252763

目录
相关文章
|
存储 缓存 安全
面试题-HashMap底层原理与HashTable的区别
字节跳动面试题-HashMap底层原理与HashTable的区别
204 0
|
SQL 关系型数据库 数据库
事务隔离级别:保障数据库并发事务的一致性与性能
事务隔离级别:保障数据库并发事务的一致性与性能
|
存储 运维 监控
什么是 SRE?一文详解 SRE 运维体系
什么是 SRE?一文详解 SRE 运维体系
3692 1
|
7月前
|
数据可视化 测试技术 API
JMeter、Apipost 与 Postman 的 API 测试对比:为什么 APIPost 是更聪明的选择
API测试如同筹备一场晚宴,选对工具至关重要。JMeter功能强大但上手难,适合专业用户;Postman简单易用,但在复杂场景和团队协作中表现有限;而Apipost则是一款智能高效的“厨房神器”。它性能测试轻松、结果清晰、学习门槛低,并且能一键集成CI/CD流程。对于追求效率与便捷的团队而言,Apipost无疑是更优选择,让API测试如同五星大厨烹饪般丝滑流畅。
|
7月前
|
网络协议 前端开发 数据可视化
Apipost免费版、企业版和私有化部署详解
Apipost 是企业级 API 研发协作一体化平台,提供 API 研发、测试、管理全链路解决方案。支持多种协议(HTTP(s)、WebSocket、gRPC 等),助力团队实时协作、降本增效。免费版适合小微团队,具备 API 设计、调试、自动化测试和文档功能;企业版强化全链路资产管理与管控,支持复杂场景测试。此外,私有化部署方案保障数据安全,提供定制化服务与专业支持,满足内网需求企业的要求。
|
8月前
|
JSON 自然语言处理 前端开发
WebSocket调试工具深度对比:Postman与Apipost功能实测解析
本文深入对比了Postman与Apipost两款WebSocket调试工具。作为实时通讯系统工程师,作者在开发智能客服系统时遇到了传统工具调试复杂、文档管理不便的问题。通过引入Apipost的智能连接池、消息分组管理和自动化文档生成等功能,实现了多环境自动切换、消息分类和接口文档自动生成,极大提升了调试效率和团队协作效果。最终,使用Apipost使接口调试时间减少40%,文档维护成本降低70%,跨团队沟通效率提升50%。
|
Java 应用服务中间件 开发者
【实战指南】Java Socket编程:构建高效的客户端-服务器通信
【6月更文挑战第21天】Java Socket编程用于构建客户端-服务器通信。`Socket`和`ServerSocket`类分别处理两端的连接。实战案例展示了一个简单的聊天应用,服务器监听端口,接收客户端连接,并使用多线程处理每个客户端消息。客户端连接服务器,发送并接收消息。了解这些基础,加上错误处理和优化,能帮你开始构建高效网络应用。
736 10
|
消息中间件 存储 NoSQL
Redis 从入门到精通之Redis 订阅与发布
Redis 是一个支持发布/订阅模式的高性能内存数据库,支持订阅频道和模式。在 Redis 中,客户端可以订阅一个或多个频道或模式,然后接收发布到这些频道或模式的消息。下面将介绍 Redis 中订阅与发布相关的命令和操作
646 74
Redis 从入门到精通之Redis 订阅与发布
|
存储 C语言
C语言单链表实现
一个用C语言编写的简单学生信息管理系统,该系统具备信息输入、成绩计算、排序、删除、查找、修改、保存和读取文件等功能。
119 0
C语言单链表实现
|
存储 人机交互 C语言
【C语言项目实战】使用单链表实现通讯录
【C语言项目实战】使用单链表实现通讯录