Comparable与Comparator

Comparable与Comparator在Java中的应用
本文详细介绍了Java中Comparable和Comparator接口的区别、作用及如何在集合操作中使用它们,包括实现排序规则、理解hashCode和equals方法的灵活运用,以及在不同场景下选择合适的比较策略。同时提供了具体的示例代码,帮助开发者更好地理解和实践。

Comparable是数据与算法结合,表现为数据绑定固有的排序算法。算法只能有一种。而Comparator可以数据与算法分离,算法可以有多种实现。

准确的讲二个接口都是实现的比较规则,都是根据业务逻辑指定比较规则。在集合或数组中使用sort方法才会达到排序的目的。

排序的目的是为了快速过滤,比如public SortedSet<E> headSet(E toElement)

使用哪些属性定义比较规则,使用哪些属性构造hashcode, equal灵活决定,并不是所有的属性都用来定义到这些方法里。比较规则返回的相对值而equal是is, identify的比较。

相对值应用还比如在cronjob的语法,就支持绝对时间与相对时间来执行任务。

一。比较

使用Comparable接口完成排序:实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键有序集合中的元素无需指定比较器

使用Comparator接口实现排序:实现其compare方法,根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数来判断大小。强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序(不使用天然的Comparable定义的比较规则得到排序的结果,而使用另一种排序算法得到结果),或者为那些没有自然顺序的对象 collection 提供排序(最初的类并没有实现Comparable接口,而之后又不想改变类的定义而实现排序,此时可以使用Comparator)。

 

Comparable目的是让集合内部存在一个默认的比较规则,Comparator是在集合外部定义比较规则。一般我们写的bean都要实现这一接口,这也是标准javabean的规范。

Comparator可以看成一种算法的实现,将算法和数据分离,Comparator也可以在下面两种环境下使用:
     1、类的设计师没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身
     2、可以使用多种排序标准,比如升序、降序等。

 

二。Comparable示例:

    private static class TaskTimmer implements Comparable<TaskTimmer>
    {
        private Date   start;
        private String taskName;

        public TaskTimmer(Date start, String taskName)
        {
            this.start = start;
            this.taskName = taskName;
        }

        public Date getStart()
        {
            return start;
        }

        public void setStart(Date start)
        {
            this.start = start;
        }

        public String getTaskName()
        {
            return taskName;
        }

        public void setTaskName(String taskName)
        {
            this.taskName = taskName;
        }

     //只要taskName相同,将来都会落到同一个hash bucket. 服务于集合元素的查询,不关心date属性值
        @Override
        public int hashCode()
        {
            return taskName.hashCode();
        }

     //服务于集合中查询。不关心date属性值
       @Override
        public boolean equals(Object obj)
        {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            TaskTimmer other = (TaskTimmer) obj;
            if (taskName == null)
            {
                if (other.taskName != null)
                    return false;
            }
            else if (!taskName.equals(other.taskName))
                return false;
            return true;
        }

     //只关心date值,时间越早TreeSet里越靠前
        @Override
        public int compareTo(TaskTimmer o)
        {
            if (this == o)
                return 0;
            if (o == null)
                return -1;
            if (o.taskName != null && this.taskName != null && this.taskName.equals(o.taskName))
            {
                return 0;
            }
            if (this.start == null || o.getStart() == null)
            {
                return -1;
            }
            else
            {
                return this.start.compareTo(o.getStart());
            }
        }
    }

 

针对集合的操作:

private TreeSet<TaskTimmer>        taskTimmers;
......
synchronized
(taskTimmers) {                    //删除需要用到hashcode,equal
    taskTimmers.remove(
new TaskTimmer(null, key)); }

       Calendar now = Calendar.getInstance(); now.add(Calendar.MINUTE, -30); Date halfHourAgo = now.getTime(); synchronized (taskTimmers) {     
//过滤使用headSet(CompareElement),将TreeSet中存活超过半个小时的TaskTimer取出并删除。过滤用到比较规则compareTo方法。
Set
<TaskTimmer> deleteTasks = taskTimmers.headSet(new TaskTimmer(halfHourAgo, null)); for (TaskTimmer taskTimmer : deleteTasks) { ..... } taskTimmers.removeAll(deleteTasks); }

 

注意,使用哪些属性定义比较规则,使用哪些属性构造hashcode, equal灵活决定,并不是所有的属性都用来定义到这些方法里。

 

三。Comparator示例

package com.gaoyibo.example.gold_example.treeset;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

/*
 * TreeMap实现 红黑树http://baike.baidu.com/view/133754.html
 */
public class TestTreeSet
{

    public TestTreeSet()
    {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        //
        System.out.println("a".compareTo("b"));
        System.out.println(-("a".compareToIgnoreCase("b")));
      /*
     * Comparator可以在TreeSet的构造方法中指定,这样表示每添加一个元素就会自动排序。
     * *另一种方式是先不考虑排序,只往里添加元素,最后使用Collections.sort(ts,new InstanceComparator());
     */
     TreeSet<String> ts = new TreeSet<String>(new InstanceComparator());
        ts.add("aa");
        ts.add("BB");
        ts.add("bb"); // BB和bb被认为是相同的元素,因为BB首先输入,所以打印的是bb
        ts.add("DD");

        //排序的结果是dd<bb<aa. aa从最小的最元素变成最大的元素。排到set的最后。
        System.out.println(ts.first());
        System.out.println(ts.last());

        loadSet(ts);

        if (ts.contains("bb"))
        {
            System.out.println("Contains bb/BB");
        }

        /*
         * 返回此 set 的部分视图,要求其元素严格小于 toElement。
         */
        TreeSet<String> subTs = (TreeSet) ts.headSet("ab");
        loadSet(subTs);

        /*
         * subTs和ts里面的元素是共享的
         */
        System.out.println("------->subTs and ts store the same objects");
        subTs.clear();
        loadSet(subTs);
        loadSet(ts);
        /*
         * 报错headSet("ab");
         * 
         * subTs.add("a");
         */
        System.out.println("------->subTs and ts store the same objects");
        subTs.add("tt");
        loadSet(ts);
        loadSet(subTs);
        ts.remove("aa");
        loadSet(ts);
        loadSet(subTs);
        
        
    }

    public static void loadSet(Set s)
    {
        Iterator iter = s.iterator();

        while (iter.hasNext())
        {
            System.out.println(iter.next());
        }
    }

}

class InstanceComparator implements Comparator
{
    /*
     * 比较用来排序的两个参数。随第一个参数小于、等于或大于第二个参数而分别返回负整数、零或正整数。 实现程序必须确保对于所有的 x 和 y 而言,都存在
     * sgn(compare(x, y)) == -sgn(compare(y, x))。(这意味着当且仅当 compare(y, x) 抛出异常时
     * compare(x, y) 才必须抛出异常。)
     * 
     * 实现程序还必须确保关系是可传递的:((compare(x, y)>0) && (compare(y, z)>0)) 意味着 compare(x,
     * z)>0。
     * 
     * 最后,实现程序必须确保 compare(x, y)==0 意味着对于所有的 z 而言,都存在 sgn(compare(x,
     * z))==sgn(compare(y, z))。
     * 
     * 虽然这种情况很普遍,但并不 严格要求 (compare(x, y)==0) == (x.equals(y))。一般说来,任何违背了这一点的
     * comparator 都应该清楚地指出这一事实。推荐的语言是“注意:此 comparator 强行进行与等号一致的排序。”
     */public int compare(Object o1, Object o2)
    {
        String text1 = o1.toString();
        String text2 = o2.toString();
        return -(text1.compareToIgnoreCase(text2)); 
//        return (text1.compareToIgnoreCase(text2));

    }

    /*
     * 
     * 比较两个comparator,和我们一个collection集合排序没有关系 因此,comp1.equals(comp2) 意味着对于每个对象引用
     * o1 和 o2 而言,都存在 sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2))。
     * 两个不同的comparator!
     */
    public boolean equals(Object obj)
    {
        return this.equals(obj);

    }
}

 

 

 

四。引用:

The methods do not have to give the same answers. That depends on which objects/classes you call them.
If you are implementing your own classes which you know you want to compare at some stage, you may have them implement the Comparable interface and implement the compareTo() method accordingly.
If you are using some classes from an API which do not implement the Comparable interface, but you still want to compare them. I.e. for sorting. You may create your own class which implements the Comparator interface and in its compare() method you implement the logic.


Comparable interface contains a method called compareTo(obj) which takes only one argument and it compares itself with another instance or objects of the same class.
Comparator interface contains a method called compare(obj1,obj2) which takes two arguments and it compares the value of two objects from the same or different classes.

    •    a.compareTo(b):
Comparable interface. Compares values and returns an int which tells if the values compare less than, equal, or greater than.
If your class objects have a natural order, implement the Comparable interface and define this method. All Java classes that have a natural ordering implement this (String, Double, BigInteger, ...).
    •    compare(a, b):
Comparator interface. Compares values of two objects. This is implemented as part of the Comparator<T> interface, and the typical use is to define one or more small utility classes that implement this, to pass to methods such as sort() or for use by sorting data structures such as TreeMap and TreeSet. You might want to create a Comparator object for the following:
    ◦    Multiple comparisons. To provide several different ways to sort something. For example, you might want to sort a Person class by name, ID, age, height, ... You would define a Comparator for each of these to pass to the sort() method.
    ◦    System class To provide comparison methods for classes that you have no control over. For example, you could define a Comparator for Strings that compared them by length.
    ◦    Strategy pattern To implement a Strategy pattern, which is a situation where you want to represent an algorithm as an object that you can pass as a parameter, save in a data structure, etc.

 

 

五。Comparator中的null处理:

不能简单的返回1或其它的值,将null的值放到最后,这样会违反一致性。通常的做法是:Handle it like null means infinitely far away. Thus comp(1234, null) == -1, comp(null, null) == 0, comp(null, 1234) == 1. With this, you get a consistent ordering. 即null值看为无穷大。

    public static class LocationPhotosComparator implements Comparator<PhotoInfo>, Serializable
    {
        private static final long serialVersionUID = 1L;
        public  static final Map<Integer, Integer> blessedIndMap       = new HashMap<Integer, Integer>();
        static
        {
            blessedIndMap.put(UserImage.S_BLESSED_GEO_PARENT,3);
            blessedIndMap.put(UserImage.S_BLESSED_GEO_ONLY,2);
            blessedIndMap.put(UserImage.S_BLESSED_PROPERTY_ONLY,1);
        }

        @Override
        public int compare(PhotoInfo o1, PhotoInfo o2)
        {
            
            if (o1 == null || o2 == null)
            {
                Logging.SERVLET.error("cannot compare null elements");
                if (o1 == null && o2 == null){
                    return 0;
                }else{
                    return o1==null?1:-1;
                }
            }
            int bind1 = getIndexByBlessed(o1.getBlessed());
            int bind2 = getIndexByBlessed(o2.getBlessed());
            if (bind1 == bind2)
            {
                //recently first show
                Date d1=o1.getPublishedDate();
                Date d2=o2.getPublishedDate();
                if(d1==null || d2==null){
                    Logging.SERVLET.error("cannot compare null elements");
                    if (d1 == null && d2 == null){
                        return 0;
                    }else{
                        return d1==null?1:-1;
                    }
                }else{
                    return -(o1.getPublishedDate().compareTo(o2.getPublishedDate()));
                }
            }
            //blessed show order 2,1,6,other
            return -(bind1 - bind2);
        }
        
        public int getIndexByBlessed(int blessed)
        {
            return blessedIndMap.get(blessed) == null ? 0 : blessedIndMap.get(blessed);
        }
    }

 

 

转载于:https://www.cnblogs.com/highriver/archive/2012/09/10/2678745.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索局部开发之间实现平衡。文章详细解析了算法的初始化、勘探开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOAMOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值