Java 常用类库(三)

本文详细介绍了Java中数组的基本操作方法,如排序、填充、比较等,并深入探讨了比较器Comparable与Comparator的使用方式及区别,同时给出了具体的代码实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Arrays类

java.util.Arrays.sort(数组名称) ”是一个数组排序操作,实际上这一个操作就是调用了java.util包中Arrays子类的sort()方法而成的,而Arrays是一个数组操作的工具类。

常用方法

方法类型描述
public static boolean equals(int[] a,int[] b)普通判断两个数组是否相等,此方法被重载多次,可判断多种数据类型的数组
public static void fill(int[] a,int val)普通将指定内容填充到数组中,此方法被重载多次,可填充多种数据类型的数组
public static void sort(int[] a)普通数组排序,……
public static int binarySearch(int[] a,int key)普通对排序后的数组进行检索,使用二分检索,……
public static String toString(int[] a)普通输出数组信息,……

Arrays类方法使用

// 使用Array类
import java.util.Arrays;
public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
    int dataA[] = new int[] {1,3,2} ;
    int dataB[] = new int[] {1,2,3} ;
    Arrays.fill(dataA, 9);
    System.out.println(Arrays.equals(dataA, dataB));
    System.out.println(Arrays.toString(dataA));
    }
}

运行结果:

false
[9, 9, 9]

比较器

首先观察一段程序:

// 自定义类没有实现比较器接口
import java.util.Arrays;

class Person {
    private String name ;
    private int age ;
    public Person(String name,int age) {
        this.name = name ;
        this.age = age ;
    }
    @Override
    public String toString() {
        return "name:" + this.name +",age:" + this.age;
    }
}
public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
    Person per[] = new Person[] {new Person("zhangsan", 20),
                new Person("lisi", 37),new Person("wangwu", 15)} ;
############ 此句会出现异常 ############
    Arrays.sort(per);       //排序
##############################
    for (int i = 0; i < per.length; i++) {
        System.out.println(per[i]);
        }
    }
}

运行结果:
Exception in thread "main" java.lang.ClassCastException: Person cannot be cast to java.lang.Comparable

观察一下Arrays类中存在的一个方法:


  • 对象数组的排序:public static void sort(Object[] a)
    查看java.util.Arrays.sort(Object[] a) 可以发现对此异常的说明:

ClassCastException - if the array contains elements that are not mutually comparable (for example, strings and integers)
如果容器内包含的元素之间不可以相互比较,则抛出ClassCastException异常。

那么怎么能让自定义类的元素之间相互比较呢,这里可以使用Comparable接口。

Comparable接口

java.lang.Comparable接口是最为常用的一个比较器,此接口定义如下:

public interface Comparable<T>{
    int compareTo(T o)
}

在Comparable接口中发现只有一个CompareTo() 方法,而此方法可以返回三种类型的数据:-1,0,1。而一个类在实现了该接口后具备有比较能力,也主要是由于覆写了compareTo(T o) 方法,通过此方法定义比较规则,而在日后对类对象比较的时候则会依次规则进行比较。

在学习String类中,也学习过CompareTo()方法,可以进行大小的判断。

//  String 中的compareTo()方法
//  Returns:
//    the value 0 if the argument string is equal to this string; a value less than 0 if 
//    this string is lexicographically less than the string argument; and a value greater than 
//    0 if this string is lexicographically greater than the string argument.
//    

public int compareTo(String anotherString);

使用Comparable接口

// 比较器的使用
import java.util.Arrays;

class Person implements Comparable<Person>{
    private String name ;
    private int age ;
    public Person(String name,int age) {
        this.name = name ;
        this.age = age ;
    }
    @Override
    public String toString() {
        return "name:" + this.name +",age:" + this.age;
    }
    // 覆写接口中的函数 compareTo();
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age) {
            return 1 ;
        }else if (this.age < o.age) {
            return -1 ;
        }else {
            return 0 ;
        }
    }
}
public class test {
    public static void main(String[] args) throws CloneNotSupportedException {
    Person per[] = new Person[] {new Person("zhangsan", 20),
                new Person("lisi", 37),new Person("wangwu", 15)} ;
    Arrays.sort(per);       // 排序
    for (int i = 0; i < per.length; i++) {
        System.out.println(per[i]);
        }
    }
}

运行结果:

name:wangwu,age:15
name:zhangsan,age:20
name:lisi,age:37

基于Comparator比较器的Binary Tree

已经有了对象之间的大小比较操作,就可以利用此概念实现二叉树。
范例:利用Comparable实现二叉树

// 自定义可比较类,生成对象存放在二叉树中
class Person implements Comparable<Person>{
    private String name ;
    private int age ;
    public Person(String name,int age) {
        this.name = name ;
        this.age = age ;
    }
    @Override
    public String toString() {
        return "name:" + this.name +",age:" + this.age;
    }
    @Override
    public int compareTo(Person o) {
        if (this.age > o.age) {
            return 1 ;
        }else if (this.age < o.age) {
            return -1 ;
        }else {
            return 0 ;
        }
    }
}

// 二叉树类定义
class BinaryTree {

    // ========= 结点定义开始 ==================
    private class Node {
        @SuppressWarnings("rawtypes")
        private Comparable data ;
        private Node left ;
        private Node right ;
        public Node(Comparable data){
            this.data = data ;
        }
        /**
         * 在结点中实现添加结点的函数
         * @param newNode
         */
        public void addNode(Node newNode) {
            if (this.data.compareTo(newNode.data) > 0) {
                if (this.left == null) {
                    this.left = newNode ;
                }else {
                    this.left.addNode(newNode);
                }
            }else {
                if (this.right == null) {
                    this.right = newNode ;  
                }else {
                    this.right.addNode(newNode);
                }
            }
        }
        /**
         * 具体实现toArray功能,此处依中序遍历输出
         */
        public void toArrayNode() {
            if (this.left != null) {        // 有左子树
                this.left.toArrayNode();
            }
            BinaryTree.this.retData[BinaryTree.this.foot ++] = this.data ;
            if (this.right != null) {
                this.right.toArrayNode();
            }
        }
    }
    // ============= 结点定义结束 ==============

    // ============= 二叉树定义开始 ============
    private Node root ;     // 根节点
    private int count ;     // 统计对象的保存个数
    private int foot ;      // 操作脚标
    private Object [] retData ;
    /**
     * 将可比较(实现Comparable接口)的数据加入此二叉树中
     * @param data(可比较数据)
     */
    public void add(Comparable data) {
        if (data == null) {
            return ;
        }
        Node newNode = new Node(data) ;
        if (this.root == null) {
            this.root = newNode ;
        }else {
            this.root.addNode(newNode) ;
        }
        this.count ++ ;         // 记录树中已有数据个数
    }

    /**
     * 将此二叉树转换为输出数组函数
     * @return retData
     */
    public Object[] toArray() {
        if (this.root == null) {
            return null ;
        }
        this.foot = 0 ;
        this.retData = new Object[this.count] ;     // 以数据量大小开辟数组
        this.root.toArrayNode();
        return this.retData ;
    }
}

// 主程序入口
public class BinaryTreeDemo {
    public static void main(String[] args) {
        BinaryTree bTree = new BinaryTree() ;
        bTree.add(new Person("张三", 20));
        bTree.add(new Person("李四", 37));
        bTree.add(new Person("王五", 15));
        Object [] data = bTree.toArray() ;
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
}

运行结果:

name:王五,age:15
name:张三,age:20
name:李四,age:37

挽救的比较器:Comparator

在工作之中使用比较器,首选Comparable,但是Comparable有一个特点,它必须在定义的时候就实现好接口。有这样一种情况,一个类已经完成,且不允许做出任何修改,此类在先期设计时没有考虑对象数组的比较问题。 此时可以使用挽救比较器:Comparator

// Comparator接口(挽救比较器)定义如下
public interface Comparator<T> {
    int compare(T o1,T o2);
    boolean equals(Object obj);
}

虽然Comparator接口中定义了两个抽象方法,但是子类只需要覆写 compare() 方法即可,而equals()方法在Object类中已经有了默认实现(地址比较)。

如果要利用Comparator接口实现对象数组的排序操作,还需要更换java.util.Arrays类中的排序方法。更改为:
public static void sort(T[] a, Comparator < ? super T> c)

比较

面试题:请解释两种解释器的区别?

  1. 如果对象数组需要进行排序,则需要使用到比较器,Java提供有两种比较器:Comparable、Comparator
  2. java.lang.Comparable是在定义类的时候实现的接口,里面有compareTo() 方法;
  3. java.util.Comparator是一个挽救的比较器,需要单独为需要比较的类定义一个新的比较规则,里面有两个方法:compare()、equals()。
  4. 分别编写代码实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值