3.8 工具类

  本节将介绍两个工具类的使用,这两个工具类的特点是类中的方法都是静态的,不需要创建对象,直接使用类名调用即可。

  Collections工具类,是集合对象的工具类,提供了操作集合的工具方法,例如排序、复制和反转排序等方法。

  Arrays工具类,是数组的工具类,提供了对数组的工具方法,例如排序、二分查找等。

3.8.1 Collections工具类常用方法

  • void sort(List list)

  根据数据元素的自然顺序对指定集合按升序进行排序。

  • void sort(List list, Comparator c)

  根据指定比较器产生的顺序对指定集合进行排序。通过自定义Comparator比较器,可以实现按程序员定义的规则进行排序。Collections工具类里很多方法都可以指定比较器进行比较和排序,这里不都列举出来。关于Comparator比较器,将会在下面的课程中介绍。

  • void shuffle(List list)

  对指定集合进行随机排序。

  • void reverse(List list)

  反转指定集合中数据元素的顺序。

  • Object max(Collection coll)

  根据数据元素的自然顺序,返回给定Collection集合中的最大元素。该方法的输入类型为Collection接口,而非List接口,因为求集合中最大元素不需要集合是有序的。在Collections工具类里静态方法中输入参数的类型,需要大家注意区分。

  • Object min(Collection coll)

  根据数据元素的自然顺序,返回给定Collection的最小元素。

  • int binarySearch(List list,Object o)

  使用二分查找法查找指定集合,以获得指定数据元素的索引。如果此集合中不包含该数据元素,则返回-1。在进行此调用之前,必须根据集合数据元素的自然顺序对集合进行升序排序(通过 sort(List list)方法)。如果没有对集合进行排序,则结果是不确定的。如果集合中包含多个元素等于指定的数据元素,则无法保证找到的是哪一个。

  • int indexOfSubList(List source,List target)

  返回指定源集合中第一次出现指定目标集合的起始位置,如果没有出现这样的集合,则返回-1。

  • int lastIndexOfSubList(List source,List target)

  返回指定源集合中最后一次出现指定目标集合的起始位置,如果没有出现这样的集合,则返回-1。

  • void copy(List dest,List src)

  将所有数据元素从一个集合复制到另一个集合。

  • void fill(List list,Object o)

  使用指定数据元素替换指定集合中的所有数据元素。

  • boolean replaceAll(List list,Object old,Object new)

  使用一个指定的新数据元素替换集合中出现的所有指定的原数据元素。

  • void swap(List list,int i,int j)

  在指定集合的指定位置处交换数据元素。

3.8.2 Collections工具类使用

  接下来通过一个例子来演示Collections工具类中静态方法的使用。

  1. import java.util.*;
  2. public class TestCollections
  3. {
  4. public static void main(String[] args)
  5. {
  6. List list = new ArrayList();
  7. list.add("w");
  8. list.add("o");
  9. list.add("r");
  10. list.add("l");
  11. list.add("d");
  12. System.out.println("排序前: " + list);
  13. System.out.println("该集合中的最大值:" + Collections.max(list));
  14. System.out.println("该集合中的最小值:" + Collections.min(list));
  15. Collections.sort(list);
  16. System.out.println("sort排序后: " + list);
  17. //使用二分查找,查找前须保证被查找集合是自然有序排列的
  18. System.out.println("r在集合中的索引为: " + Collections.binarySearch(list,"r"));
  19. Collections.shuffle(list);
  20. System.out.println("再shuffle排序后: " + list);
  21. Collections.reverse(list);
  22. System.out.println("再reverse排序后: " + list);
  23. Collections.swap(list,1,4);
  24. System.out.println("索引为1、4的元素交换后:" + list);
  25. Collections.replaceAll(list,"w","d");
  26. System.out.println("把w都换成d后的结果: " + list);
  27. Collections.fill(list,"s");
  28. System.out.println("全部填充为s后的结果: " + list);
  29. }
  30. }

  编译、运行程序,运行结果如图3.8所示。

3.8 工具类 - 图1


图3.8 Collections工具类使用

3.8.3 Comparable与Comparator

  之前我们使用了Comparable接口实现了在TreeSet集合中的自定义排序。这种方法是通过在集合内的元素类中,实现compareTo(Object o)方法进行元素和元素之间的比较、排序的。因为是在类内部实现比较,所以可以将Comparable称为内部比较器。

  由实现了Comparable接口的类组成的集合,可使用Collections工具类的sort(List list)方法进行排序,排序规则是由compareTo(Object o)方法确定的。TreeSet集合是一个有序的Set集合,默认即按照Comparable接口的排序规则进行排序。而其他List集合,默认是按照用户添加元素的顺序进行排序的,要想让集合元素按照Comparable接口的排序规则进行排序,需要使用Collections工具类的sort(List list)方法。String、Integer等一些类已经实现了Comparable接口,所以将这些类加入List集合中,就可以直接进行排序了。

  接下来通过一个案例来说明Collections工具类的sort(List list)方法对集合内元素实现Comparable接口的依赖,具体代码如下:

  1. import java.util.*;
  2. public class TestComparable
  3. {
  4. public static void main(String[] args)
  5. {
  6. //用LinkedList存储学生对象
  7. LinkedList stuLL = new LinkedList();
  8. stuLL.add(new Student("王云",1));
  9. stuLL.add(new Student("南天华",3));
  10. stuLL.add(new Student("刘静涛",2));
  11. stuLL.add(new Student("张平",3));
  12. //使用sort方法进行排序
  13. Collections.sort(stuLL);
  14. Iterator it = stuLL.iterator();
  15. while (it.hasNext()) {
  16. System.out.println(it.next());
  17. }
  18. }
  19. }
  20. class Student{
  21. int stuNum = -1;
  22. String stuName = "";
  23. Student(String name, int num) {
  24. this.stuNum = num;
  25. this.stuName = name;
  26. }
  27. public String toString() {
  28. return "学号为:" + stuNum + "的学生,姓名为:" + stuName;
  29. }
  30. }

  编译、运行,程序运行时抛出异常,提示Student类没有实现Comparable接口,无法进行排序。修改上面的Student类,实现Comparable接口的compareTo(Object o)方法,具体代码如下:

  1. //按学号进行降序排序,学号相同按姓名排序
  2. class Student implements Comparable{
  3. //省略其他代码
  4. //实现Comparable接口的compareTo(Object o)方法
  5. public int compareTo(Object o) {
  6. Student input = (Student) o;
  7. int res = stuNum < input.stuNum ? 1 : (stuNum == input.stuNum ? 0 : -1);
  8. if (res == 0) {
  9. res = stuName.compareTo(input.stuName);
  10. }
  11. return res;
  12. }
  13. }

  再次编译、运行程序,运行结果如图3.9所示。

3.8 工具类 - 图2


图3.9 Comparable比较器的使用

  既然将Comparable称为内部比较器,那么自然就会想到应该有外部比较器。接下来要隆重推出的就是Comparator外部比较器,也就是在学习Collections工具类的sort(List list, Comparator c)方法时提到的比较器。

  Comparator可以理解为一个专用的比较器,当集合中的对象不支持自比较或者自比较的功能不能满足程序员的需求时,可以写一个比较器来完成两个对象之间的比较,从而实现按比较器规则进行排序的功能。

  接下来,通过在外部定义一个姓名比较器和一个学号比较器,然后在使用Collections工具类的sort(List list,Comparator c)方法时选择使用其中一种外部比较器,对集合里的学生信息按姓名、学号分别排序输出,具体代码如下:

  1. import java.util.*;
  2. //定义一个姓名比较器
  3. class NameComparator implements Comparator {
  4. //实现Comparator接口的compare()方法
  5. public int compare(Object op1, Object op2) {
  6. Student eOp1 = (Student)op1;
  7. Student eOp2 = (Student)op2;
  8. //通过调用String类compareTo()方法进行比较
  9. return eOp1.stuName.compareTo(eOp2.stuName);
  10. }
  11. }
  12. //定义一个学号比较器
  13. class NumComparator implements Comparator {
  14. //实现Comparator接口的compare方法
  15. public int compare(Object op1, Object op2) {
  16. Student eOp1 = (Student)op1;
  17. Student eOp2 = (Student)op2;
  18. return eOp1.stuNum - eOp2.stuNum;
  19. }
  20. }
  21. public class TestComparator
  22. {
  23. public static void main(String[] args)
  24. {
  25. //用LinkedList存储学生对象
  26. LinkedList stuLL = new LinkedList();
  27. stuLL.add(new Student("王云",1));
  28. stuLL.add(new Student("南天华",3));
  29. stuLL.add(new Student("刘静涛",2));
  30. //使用sort方法,按姓名比较器进行排序
  31. Collections.sort(stuLL,new NameComparator());
  32. System.out.println("***按学生姓名顺序输出学生信息***");
  33. Iterator it = stuLL.iterator();
  34. while (it.hasNext()) {
  35. System.out.println(it.next());
  36. }
  37. //使用sort方法,按学号比较器进行排序
  38. Collections.sort(stuLL,new NumComparator());
  39. System.out.println("***按学生学号顺序输出学生信息***");
  40. it = stuLL.iterator();
  41. while (it.hasNext()) {
  42. System.out.println(it.next());
  43. }
  44. }
  45. }
  46. //定义学生对象,未实现Comparable接口
  47. class Student{
  48. int stuNum = -1;
  49. String stuName = "";
  50. Student(String name, int num) {
  51. this.stuNum = num;
  52. this.stuName = name;
  53. }
  54. public String toString() {
  55. return "学号为:" + stuNum + "的学生,姓名为:" + stuName;
  56. }
  57. }

  程序运行结果如图3.10所示。

3.8 工具类 - 图3


图3.10 Comparator比较器的使用

3.8.4 Arrays工具类使用

  Arrays类是操作数组的工具类,和Collections工具类相似,它提供的所有方法都是静态的。Arrays类主要有以下功能:

  • 对数组进行排序。

  • 给数组赋值。

  • 比较数组中元素的值是否相当。

  • 进行二分查找。

  接下来通过一段代码,演示Arrays工具类的使用,具体代码如下:

  1. import java.util.Arrays;
  2. public class TestArrays{
  3. public static void output(int[] a){
  4. for(int num:a){
  5. System.out.print(num + " ");
  6. }
  7. System.out.println();
  8. }
  9. public static void main(String[] args) {
  10. int[] array = new int[5];
  11. //填充数组
  12. Arrays.fill(array, 8);
  13. System.out.println("填充数组Arrays.fill(array,8):");
  14. TestArrays.output(array);
  15. //将数组索引为1到4的元素赋值为6
  16. Arrays.fill(array, 1, 4, 6);
  17. System.out.println("将数组索引为1到4的元素赋值为6 Arrays.fill(array, 1, 4, 6):");
  18. TestArrays.output(array);
  19. int[] array1 = {12,9,21,43,15,6,19,77,18};
  20. //对数组索引为3到7的元素进行排序
  21. System.out.println("排序前,数组的序列为:");
  22. TestArrays.output(array1);
  23. Arrays.sort(array1,3,7);
  24. System.out.println("对数组索引为3到7的元素进行排序:Arrays.sort(array1,3,7):");
  25. TestArrays.output(array1);
  26. //对数组进行自然排序
  27. Arrays.sort(array1);
  28. System.out.println("对数组进行自然排序 Arrays.sort(array1):");
  29. TestArrays.output(array1);
  30. //比较数组元素是否相等
  31. int[] array2 = array1.clone();
  32. System.out.println("数组克隆后是否相等:Arrays.equals(array1, array2):" +
  33. Arrays.equals(array1, array2));
  34. //使用二分查找法查找元素下标(数组必须是排序好的)
  35. System.out.println("77在数组中的索引:Arrays.binarySearch(array1, 77):"
  36. \+ Arrays.binarySearch(array1, 77));
  37. }
  38. }

  编译、运行程序,其运行结果如图3.11所示。

3.8 工具类 - 图4


图3.11 Arrays工具类的使用