Java,如何添加“比较器”类来增加代码的可重用性

时间:2009-11-06 15:50:15

标签: java comparator

前言:我代表一位朋友(显然是害羞地自己发布)发布此内容,我浏览了相关问题,但我似乎没有发现任何重复...但请注意我不要根本不懂Java,所以如果这是重复的话我会提前道歉!

这是代码的一部分:

public class ElencoEsami implements Comparable{
    private ArrayList<EsameMedico>  a = new ArrayList<EsameMedico>();
    private Comparable comparatore;
    public ElencoEsami() {
    }
    public void addEsame(EsameMedico e) {
        if (a.isEmpty()) {
            a.add(0,e);
            return;
        }

        for(int i=0;i<a.size();i++) {
            if (a.get(i).getData().after(e.getData())) {
                a.add(i,e);
                break;
            }
        }
        a.add(e);
    }
    public int compareTo(Object o) {
// ?????
    }

}

我的朋友希望实现“addEsame”,以便最大化代码可重用性,特别是他希望能够通过添加新类(比较器)来更改列表的排序方式(现在按名称排序)我相信哪个类?或者至少我会用C ++来做这件事。)

谢谢!

8 个答案:

答案 0 :(得分:10)

首先,使用Collections.sort(List list,Comparator c)

然后,编码尽可能多的Comparator,因为您需要排序顺序

就是这样。

答案 1 :(得分:4)

通常,如果您希望能够使用比较器对列表重新排序,则不需要实现Comparable(仅适用于一个排序),您可以创建新的Comparator对象,这些对象可以写在该类之外并且可以指定任何可能的排序(由该类中的吸气者)

你需要的只是比较器的一个setter(该类中的一个字段),它在更改后对你的列表进行调整。

从另一个类看起来像:

your_object.setComparator(new Comparator<ElencoEsami>() {
    public int compare(ElencoEsami o1, ElencoEsami o2) {
        // do some comparing...
    }
});

在你的课堂上,它看起来像是:

public void setComparator(Comparator<? extends ElencoEsami> comp) {
    this.comparator = comp;
    Collections.sort(this.listOfItems, comp);
}

答案 2 :(得分:3)

如果我想以可重用的方式实现多个比较器,我希望将它们实现为枚举(基于来自Old Tech Per的想法):

public class EsameMedico {
    ...

    /** Enumeration of {@link Comparator}s for {@code EsameMedico}. */
    public static enum Comparators implements Comparator<EsameMedico> {
        /** Compares by name. */
        BY_NAME {
            public int compare(final EsameMedico em1, final EsameMedico em2) {
                return em1.name.compareTo(em2.name);
            }

            public void sort(final List<EsameMedico> l) {
                Collections.sort(l, BY_NAME);
            }
        },
        /* Compares by whatever. */
        BY_WHATEVER {
            public int compare(final EsameMedico em1, final EsameMedico em2) {
                return /* compare by "whatever" */;
            }

            public void sort(final List<EsameMedico> l) {
                Collections.sort(l, BY_WHATEVER);
            }
        };

        /** Sorts the list by this criterion. */
        public abstract void sort(List<EsameMedico> l);
    }

    ...
}

但请注意,对于列表,您必须自己在插入时维护列表的顺序。如果您希望自动对集合进行排序,SortedSet可能会有所帮助。 TreeSetSortedSet接口的一个实现,在其构造函数中使用Comparator并对其元素进行排序。

答案 3 :(得分:2)

Sun在Java接口路径中有一个关于Object Ordering的页面。它简要概述了比较器以及如何编写它们。

答案 4 :(得分:1)

如果您想更改列表的顺序,可以使用Collections.sort()作为参数的comparator方法。

根据您的代码,您似乎在ComparableComparator接口之间存在一些混淆。实现Comparable接口的类意味着它具有某种自然顺序(例如,Integer类基于它所代表的int自然排序)。使用比较器,您可以根据其他一些订购标准订购对象。

根据您发布的代码,我想询问您是否真的打算订购ElencoEsami课程,或者您是否打算订购EsameMedico对象?

如果是应该订购的EsameMedio类,那么应该实现Comparable接口的EsameMedico类。假设您在addEsame()方法中进行的比较是EsameMedico类的自然顺序,您可以在EsameMedico中实现compareTo()方法,如下所示:

public class EsameMedico implements Comparable<EsameMedico>{
  ...
  public int compareTo(Object o) {
    EsameMedico e = (EsameMedico)o;
    if(getData().after(e.getData())) {
        return 1;
    } else if(e.getData().after(getData())){
        return -1;
    } else {
        return 0;
    }
}

}

然后,您可以将addEsame()方法更改为只需插入列表并在每次插入后调用Collections.sort()。当然,更好的方法是使用TreeSet而不是ArrayList。如果您这样做,每个EsameMedico将根据其自然顺序插入,您不必自己执行任何排序。

答案 5 :(得分:1)

如果您希望在使用addEsame添加对象时对对象进行排序,而不调用Collections.sort(),请使用带有要排序的密钥的TreeMap。如果您的对象不同,请使用TreeSet

另一件事:

按照以下方式声明您的列表:

private List<EsameMedico> a;

(或MapSet,无论您选择什么)

并在构造函数中初始化它:

a = new ArrayList<EsameMedico>();

(或TreeMap ...)

因为如果你扩展课程ElencoEsami,你会得到一些奇怪的结果。

答案 6 :(得分:1)

  1. 使用排序方法而不是“手动排序”;
  2. 正如twolfe18所指出的那样,使用Comparator对象,并仔细查看Strategy design pattern内部。

答案 7 :(得分:0)

我发现这个例子非常有用: http://www.javabeat.net/tips/20-sorting-custom-types-in-java.html

对我而言,关键是Comparator类的一个例子:

package tips.sort;

import java.util.Comparator;

public class MovieComparator implements Comparator<Movie>{

@Override
public int compare(Movie movie1, Movie movie2) {

    int rank1 = movie1.getRank();
    int rank2 = movie2.getRank();

    if (rank1 > rank2){
        return +1;
    }else if (rank1 < rank2){
        return -1;
    }else{
        return 0;
    }
}

}