【问题标题】:How to use the Comparator interface如何使用比较器接口
【发布时间】:2013-04-14 03:24:39
【问题描述】:

我是 java 新手,我并没有真正了解如何使用比较器接口。 我在Inventory 类和Item 类中有Items 中的ArrayList。 在Item 类中我写道:

public class Item implements Comparator<Item> {
    //stuff
    ...
    @Override
    public int compare(Item a, Item b) {
        if (a.getID().compareToIgnoreCase(b.getID())>0)
            return 1;
        else if (a.getID().compareToIgnoreCase(b.getID())<0)
            return -1;
        else
            return 0;
    }
}

getID() 方法只给出了 id,我必须用它来按字母顺序排列项目。 我不确定这是否正确,它让我放了@Override 注释,我不知道为什么。我还写了一个界面,上面写着:

 public interface Comparator<Item>
{
    int compare(Item a, Item b);
}

我不确定那一点。另外我如何实现这个方法来对库存类中创建的arraylist进行排序?

谢谢,如果我的问题没有意义或需要澄清,请告诉我。

【问题讨论】:

  • 等等,你的Item 类实现了Comparator,它的定义需要一个通用的Item 才能工作。看来你这里不需要通用接口...
  • 泛型接口是什么意思?
  • @bassandguitar,老兄,检查我更新的答案。我想这就是你想要的。

标签: java interface sorting comparator


【解决方案1】:

编辑:首先,有几点:

  1. @Override 注释不应是强制性的。如果 Eclipse 想让你戴上它,别担心。
  2. 不要编写自己的 Comparator 接口。删除该定义 NAO 并使用 Java 提供的定义。 重新发明轮子可能以大约 15 种不同的方式违反了计算机编程的潜规则。在代码的最顶部(public class 之前)使用 import java.util.Comparator;,以 a) 使用 Java 提供的版本,b) 使您的代码与世界上几乎所有其他存在的东西兼容。

Comparator 接口不用于创建可以自行排序的类。这是 Comparable 接口。

两者相似,所以我将在此处进行描述。

java.util.Comparator

如您所知,Comparator 接口有一种方法:compare。比较器是通用的(使用尖括号&lt;&gt;)并采用它将在&lt;&gt; 中比较的类型。问题是比较器用于比较其他类的项目。例如,我可以为 java.lang.Integers 创建一个比较器,它返回与“自然顺序”相反的结果(整数通常是如何排序的)。

比较器主要用于在其他对象不按自然顺序时为其他对象提供一种对其参数进行排序的方法。例如,java.util.TreeSet class 采用 Comparator 作为其排序功能。

java.lang.Comparable

Comparable 的目的是说一个对象可以进行比较。它也是通用的,并采用可以与之比较的类型。例如,Comparable&lt;String&gt; 可以与字符串进行比较。

Comparable 有一种方法:compareTo()。与 Comparator 的 compare() 不同,compareTo 采用一个参数。它像compare 一样工作,只是它使用调用对象作为一个参数。所以,comparableA.compareTo(comparableB)comparator.compare(comparableA, comparableB) 相同。

Comparable 主要建立对象的自然顺序,是比较对象的默认方式。比较器的作用是在对数据比较或排序有不同需求时覆盖这种自然顺序。

数组列表排序

要对List 进行排序,您可以使用已有的方法:在java.util.Collections class 上向下滚动到sort。一种方法需要一个比较器,另一种不需要。 sort 是静态的;使用Collections.sort(...),而不是Collections c = new Collections(); c.sort(...)。 (Collections 甚至没有构造函数,所以 meh。)

【讨论】:

  • Java 8 Comparator 确实有更多方法,例如here,这使得使用它更加舒适。这只是为我节省了一些苦差事,所以我认为提及它可能很有用。 :)
【解决方案2】:

要使用Comparator 接口,您必须实现它并将其作为匿名类传递给Collections.sort(List list, Comparator c) 作为第二个参数。

如果您只想将列表传递给Collections.sort(List list),那么您的Item 类必须实现Comparable 接口。

所以在这两种情况下,Collections.sort 方法都知道如何对列表中的元素进行排序

这里是一些示例代码:

实现Comparable的项目类+持有项目列表的库存

public class Item implements Comparable<Item> {

    String id = null;

    public Item(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return id;
    }

    @Override
    public int compareTo(Item o) {
        return - id.compareToIgnoreCase(o.id);
    }
}


public class Inventory {

    List<Item> items = new ArrayList<>();

    public void addItem(Item item) {
        items.add(item);
    }

    public static void main(String[] args) {
        Inventory inventory = new Inventory();
        inventory.addItem(new Item("2"));
        inventory.addItem(new Item("4"));
        inventory.addItem(new Item("1"));
        inventory.addItem(new Item("7"));

        Collections.sort(inventory.items, new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return o1.id.compareToIgnoreCase(o2.id);
            }
        });
        System.out.println(inventory.items);

        Collections.sort(inventory.items);
        System.out.println(inventory.items);

    }
}

输出

[1, 2, 4, 7] // ascending
[7, 4, 2, 1] // descending since the compareTo method inverts the sign of the comparison result.

【讨论】:

    【解决方案3】:

    您正在混淆接口 ComparatorComparable

    比较器:http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html

    可比:http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html

    Comparator 的用途是一个可以传递给需要排序的操作的类(当场匿名声明或以其他方式声明),它定义了将在项目上使用的排序。 比较器将在需要排序的类之外使用,如果您想通过其他方式对其进行排序。

    Comparable 的目的是说(实现 Comparable 的)类具有自然顺序 - 这就是它的本质。 如果您需要排序的类具有自然排序,则将其定义为 Comparable。(实现 Comparable 排序顺序的类仍然可以被 Comparator 覆盖。另一方面,如果该类不是Comparable 比通过 Comparator 是强制性的,以便订购成为可能。)

    【讨论】:

    • 我所知道的是我必须在 item 类上使用 implements Comparator,然后我如何在 inventory 类中使​​用可比较?
    • @bassandguitar 你错了——Item 将实现Comparable,或者Inventory 将接受一个Comparator,它将用于对其Items 进行排序。
    • 如何使用 compareTo() 方法对库存类中的数组进行排序?
    • @bassandguitar 允许排序的操作检查它们正在排序的对象的类是否实现了 Comparable。如果是,它使用类的 compareTo() 定义。
    【解决方案4】:

    你实现了错误的接口,你想要Comparable

    【讨论】:

    • 请说明Comparable的使用方式。
    【解决方案5】:

    @Override 注释的使用是 eclipse、netbeans 等编辑器的标准做法,用于通知开发人员他正在覆盖/实现父类/接口方法。它是可选的。

    不要在你的 Item 类中实现这个接口。创建一个 new 类并实现Comparator 接口。

    public class ItemCompare implements Comparator<Item> {
    
        @Override
        public int compare(Item a, Item b) {
            if (a.getID().compareToIgnoreCase(b.getID())>0)
                return 1;
            else if (a.getID().compareToIgnoreCase(b.getID())<0)
                return -1;
            return 0;
        }
    } 
    

    然后,在你的主类中,这样做:

    ArrayList al = new ArrayList<Item>
    
    Collections.sort(al, new ItemCompare())
    

    【讨论】:

    • 你错了,Comparator和Comparable都是接口。您的其余答案都可以。
    • 哦,感谢您指出这一点。傻我。出了点问题。
    • 我想我明白了,虽然我刚刚看到作业说要使用 compareTo() 方法,但我将如何使用它呢?所以 ItemCompare 需要是它自己的类?
    • @bassandguitar 如果作业说使用 compareTo(),compareTo() 是 Comparable 的方法,而不是 Comparator。因此,为 Item 实现 Comparable 并从那里开始。
    • @RaviTrivedi 我明白你在说什么。我只是指出您使用的是Comparable 接口,因为使用了Comparator。我编辑了您的帖子以修复它,但尚未审核。 编辑:它有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多