• 菜鸡的Java笔记 comparator 比较器


            1.数组操作类: Arrays
            2.两种比较器的使用: Comparable Comparator
            3.实现二叉树算法
            
        content (内容)
            1.数组操作类: Arrays
                Arrays 类一早就开始使用了。最早使用的是它的排序操作,但是现在打开 Arrays 观察一下有那些方法
                    二分查找法: public static int binarySearch(数据类型[] a,数据类型 key)
                    数组比较: public static boolean equals(数据类型[] a,数据类型[] a2)
                    数组的填充: public static void fill(数据类型[] a,数据类型 val)
                    数组转换为String输出: public static String toString(数据类型[] a)
                
                范例:二分查找

    package cn.mysterious.study3;
    
    import java.util.Arrays;
    
    public class StudyComparator {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int data [] = new int[]{1,29,93,44,55,666,7,788,99};
            java.util.Arrays.sort(data);
            System.out.println(Arrays.binarySearch(data, 7));
        }
    
    }

                   
                范例:数组比较

    package cn.mysterious.study3;
    
    import java.util.Arrays;
    
    public class StudyComparator {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int dataA [] = new int[]{1,29,93,44,55,666,7,788,99};
            int dataB [] = new int[]{1,29,93,44,55,666,7,788,99};
            System.out.println(Arrays.equals(dataA, dataB));
        }
    
    }

                   
                范例:数组填充

    package cn.mysterious.study3;
    
    import java.util.Arrays;
    
    public class StudyComparator {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int data [] = new int[]{1,29,93,44,55,666,7,788,99};
            Arrays.fill(data, 10);
            System.out.println(Arrays.toString(data));
        }
    
    }

                   
                在 Arrays 类中几乎包含了所有可能使用到的数组相关操作 重要的是这些方法的原理因为面试题或面试上会问到
                
                
            2.比较器: Comparable
                在 Arrays 类中提供有一个方法: public static void sort(Object[] a)
                此方法可以直接针对对象数组进行排序的操作
                但是如果现在真的要进行对象数组的排序,并不是意味着直接调用次方法即可
                如果直接调用就有可能出现如下的错误信息:
                    Exception in thread "main" java.lang.ClassCastException:
                    cn.mysterious.study3.Person cannot be cast to java.lang.Comparable
                    
                之所以造成这样的问题,是因为如果要想进行对象数组的排序,必须要解决数据大小关系的问题,然而对象无法区分出大小关系
                那么为了解决这样的问题 java 会自动的在排序的时候将所有的对象强制转换为 Comparable 接口对象
                也就是说如果要想实现对象数组的自动排序,那么对象所在的类一定要实现 Comparable 接口

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

                String 累中的 comparaTo() 方法本身就是覆写了 Comparable 接口中的 comparaTo() 方法,而如果说用户现在需要进行排序
                实际上只需要返回三个内容即可:0,-1,1
                
                范例:对象数组的排序实现

    package cn.mysterious.study3;
    
    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;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "姓名:" + this.name + ",年龄:" + this.age + "
    ";
        }
        @Override
        public int compareTo(Person o) {
            // TODO Auto-generated method stub
            if (this.age > o.age) {
                return 1;
            }else if(this.age > o.age){
                return -1;
            }else {
                return 0;
            }
            // 简化操作: return this.age - o.age;
        }
    }
    public class StudyComparator {
    
        public static void main(String[] args) {
            Person per[] = new Person[]{
                    new Person("小少爷",15),
                    new Person("大少爷",35),
                    new Person("二少爷",28),
            };
            Arrays.sort(per);
            System.out.println(Arrays.toString(per));
        }
    
    }

                   
                结论:以后不管何种情况下,只要是进行对象数组的排序,一定要使用 Comparable 接口完成
                
            实现二叉树算法( Binary Tree ,(简称:BT) )
                二叉树也好,链表也好,本质是一样的,目的就是为了保存数据,实现动态的对象数组
                所有的数据结构都一定有一个前提:必须痛过节点来进行数据的包裹,目的:确定先后顺序
                那么现在也对 Node 进行修改,让其可以保存对象( Object Comparable ),但是现在每个节点上要保留有两个子节点:左子树,右子树
                保存的原则:比根节点小的数据放在左子树,比根节点大于等于的数据保存的右子树
                
                最后按照中序遍历(左-根-右)的方式可以取得内容,所以数据是排序后的结果
                
                范例:实现基础的二叉树 StudyTwoForkTree

    package cn.mysterious.study3;
    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;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "姓名:" + this.name + ",年龄:" + this.age + "
    ";
        }
        @Override
        public int compareTo(Person o) {
            return this.age - o.age;
        }
    }
    class BinaryTree{ // 二叉树的实现类
        private class Node{ // 数据结构中必须有 Node 类,负责保存数据以及节点的关系匹配
            @SuppressWarnings(value = "rawtypes")
            private Comparable data;
            private Node left;//比根节点小的内容
            private Node rigth;//比根节点大或等于的内容
            @SuppressWarnings("unused")
            public Node( @SuppressWarnings("rawtypes") Comparable data){
                this.data = data;
            }
            @SuppressWarnings("unchecked")
            public void addNode(Node newNode) {
                // TODO Auto-generated method stub
                if (this.data.compareTo(newNode.data) > 0) { // 保存在左边
                    if (this.left == null) {
                        this.left = newNode;
                    }else {
                        this.left.addNode(newNode);
                    }
                }else {
                    if (this.rigth == null) {
                        this.rigth = newNode;
                    } else {
                        this.rigth.addNode(newNode);
                    }
                }
            }
            public void toArrayNode() {
                // TODO Auto-generated method stub
                if (this.left != null) {// 有左节点
                    this.left.toArrayNode();
                }
                BinaryTree.this.retData[BinaryTree.this.foot ++] = this.data;
                if (this.rigth != null) {
                    this.rigth.toArrayNode();
                }
            }
        }
        //****** 编写 BinaryTree 的操作 ******
        private Node root; //必须保留根节点
        private int count = 0;
        private int foot = 0;
        private Object[] retData;
        @SuppressWarnings("rawtypes")
        public void add(Object obj) { //数据的追加
            Comparable data = (Comparable)obj;
            Node newNode = new Node(data);// 将数据包装在 Node 节点之中
            if (this.root == null) {
                this.root = newNode;
            }else {
                this.root.addNode(newNode);
            }
            this.count ++;
        }
        public Object[] toArray(){
            if (this.count > 0) {
                this.foot = 0;
                this.retData = new Object[this.count];
                this.root.toArrayNode();
                return this.retData;
            } else {
                return null;
            }
        }
    }
    public class StudyTwoForkTree {
    
        public static void main(String[] args) {
            BinaryTree bt = new BinaryTree();
            bt.add(new Person("小少爷",15));
            bt.add(new Person("大少爷",35));
            bt.add(new Person("二少爷",28));
            System.out.println(Arrays.toString(bt.toArray()));
        }
    
    }

                   
                    如果想收入高一些的可以适当的把代码写的完善一些
                    
            比较器: Comparator
                通过 Comparable 的观察可以发现,如果一个类的对象要想进行对象数组排序,那么这个类在定义的时候就必须明确的实现好 Comparable 接口
                但是有没有这样一种可能性出现,一个类原本定义完成了,原本是没有排序要求的,可是后期却需要追加排序,并且这个类已经不能够修改了
                那么在这种情况下,就可以利用另外一个接口完成排序: java.util.Comparator 接口
                此接口定义如下:

        @FunctionalInterface
        public interface Comparator<T>public int compare(T o1,T o2)
            public boolean equals(Object obj)
        }

                   
                如果要想继续使用 Arrays 实现排序操作,那么就必须观察新的排序方法:
                    排序: public static <T> void sort(T[] a,Comparator<? super T> c)
                    
                范例:定义一个单独的 Person 类

    class Person {
        private String name;
        private int age;
        public Person(){}
        public Person(String name,int age){
            this.name  = name;
            this.age = age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "姓名:" + this.name + ",年龄:" + this.age + "
    ";
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public String getName() {
            return name;
        }
    }

                       
                    前提: Person 类不允许发生改变
                    
                范例:实现单独的比较器

    package cn.mysterious.study3;
    
    import java.util.Comparator;
    
    class Person {
        private String name;
        private int age;
        public Person(){}
        public Person(String name,int age){
            this.name  = name;
            this.age = age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "姓名:" + this.name + ",年龄:" + this.age + "
    ";
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public String getName() {
            return name;
        }
    }
    class PersonComparator implements Comparator<Person>{
        @Override
        public int compare(Person o1, Person o2) {
            // TODO Auto-generated method stub
            return o1.getAge() - o2.getAge();
        }
    }
    public class ComparatorClass {
        public static void main(String[] args) {
            Person per[] = new Person[]{
                    new Person("小少爷",15),
                    new Person("大少爷",35),
                    new Person("二少爷",28),
            };
            Arrays.sort(per,new PersonComparator()); // 编写排序
            System.out.println(Arrays.toString(per));
        }
    }

                   
                面试题:请解释两种比较器的区别?
                    在进行对象数组排序的过程之中需要使用到比较器,比较器有两个: Comparator Comparable
                    java.util.Comparable :是在类定义的时候默认实现好的接口。里面提供有一个 comparaTo() 方法用于比较大小
                    java.util.Comparator :需要单独定义一个排序的比较规则类,里面有两个方法: compare(),equals()

        总结
            以后如果开发中考虑到排序的需求,优先考虑使用 Comparable 接口,不到万不得已不要使用 Comparator



  • 相关阅读:
    媒体查询
    H5 progress标记
    sqlite数据库常用语句
    C#导出Word文档开源组件DocX
    bat实现监控进程守护程序-保证平台服务的稳定执行
    windows开机自动执行bat脚本启动cmd命令窗口并执行命令,最后自动关闭cmd命令窗
    Python实现定时执行任务的三种方式简单示例
    bat实现守护程序保证平台正常运行
    Windows CMD命令大全
    Windows下使用批处理文件.bat删除旧文件
  • 原文地址:https://www.cnblogs.com/mysterious-killer/p/10123711.html
Copyright © 2020-2023  润新知