@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));
}
}
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));
}
}
案例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);
}
}
}
如果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表达式比较熟悉的话,可以重构一下上面的代码。
上述代码使用匿名内部类的方式实现了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));
}
}
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));
}
}
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));
}
}
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));
}
}