编写Java Comparator

时间:2012-05-09 09:20:23

标签: java vector sorting comparator

我创建了一个Vector对象,将Table对象中的数据存储为Vector<Table>Vector<Table>包含以下组件。

[Vector<Record> records, String tableName, String keyColumnName, int recordCount, int columnCount]

我需要将上面Vector中的tableName排序为我自己的顺序,并将Vector<Table>sorted tableNames一起返回给其他进程。

我写了如下方法。

private Vector<Table> orderTables(Vector<Table> loadTables) {

    List<String> tableNames = new ArrayList<String>();

    for (Table table : loadTables) {

        String tblName = table.getTableName();
        tableNames.add(tblName);

    }
    Collections.sort(tableNames, new MyComparable());

    return null;
}

但我不知道如何写Comparator。我自己的排序顺序存储在.properties文件中。我可以读它并获得价值。但我不知道如何比较它。

我怎么能这样做?

3 个答案:

答案 0 :(得分:4)

在澄清之前

您需要为委托给Comparator比较器的Table个对象编写tableName

new Comparator<Table>() {
    @Override public int compare(Table one, Table two) {
        return one.getTableName().compareTo(two.getTableName());
    }
}

请注意这会考虑具有相同名称的Table。如果您将这些表放在HashMapHashSet中,这可能会搞砸。为避免这种情况,您可以检测到这种情况,如果表名相同,则返回one.hashCode() - two.hashCode()

Guava's ComparisonChain是编写此类多阶段比较的便捷方式:

new Comparator<Table>() {
    @Override public int compare(Table one, Table two) {
        return ComparisonChain.start()
                 .compare(one.getTableName(), two.getTableName())
                 .compare(one.hashCode(), two.hashCode())
                 .result();
    }
}

澄清后

好的,问题是强加预定义的排序顺序,而不是按名称排序Table。在这种情况下,您需要创建一个知道Comparator文件中定义的排序的.properties

实现此目的的一种方法是初始化表名到映射顺序索引的映射,并在比较期间引用该映射。鉴于财产价值:

SORT_ORDER = SALES,SALE_PRODUCTS,EXPENSES,EXPENSES_ITEMS

映射应如下所示:

{
    SALES: 0,
    SALE_PRODUCTS: 1,
    EXPENSES: 2,
    EXPENSES_ITEMS: 3
}

以下是比较器的样子:

private static class PredefinedOrderComparator implements Comparator<Table> {

    public PredefinedOrderComparator() {

        // Initialize orderIndex here

    }

    private final Map<String, Integer> orderIndex;

    @Override public int compare(Table one, Table two) {
        return orderIndex.get(one.getTableName()) - orderIndex.get(two.getTableName());
    } 

}

要从属性值填充orderIndex,您需要:

  1. 如您所述,使用getProperty()获取以逗号分隔的列表
  2. 在逗号上拆分该值(我建议使用Guava's Splitter,但String.split或其他人也可以使用)
  3. 初始化新的HashMap<String, Integer>int index = 0
  4. 遍历拆分令牌,将当前令牌映射到index并增加index
  5. 请注意隐含的假设,即所有表名都没有逗号。

答案 1 :(得分:1)

我给你写了一个关于如何使用Comparator的非常简单的例子。如果你创建一个名为Main的类,复制粘贴到其中的内容,编译并运行它,你可以看到发生了什么。

比较器只需要实现一个接口。为此,它需要实现一个方法(public int compare(T arg0,T arg1)。在那里你指定一个集合将如何排序;在这种情况下根据alfabet。

我希望这会对你有所帮助。

import java.util.*;

public class Main {

    public static void main(String[] args) {
        System.out.println("Start\n");
        List<Item> items = new ArrayList<Item>();
        for(String s : new String[]{"mzeaez", "xcxv", "hjkhk", "azasq", "iopiop"}) {
            items.add(createItem(s));
        }
        System.out.println("Items before sort:");
        System.out.println(Item.toString(items));
        Collections.sort(items, new ItemComparator());
        System.out.println("Items after sort:");
        System.out.println(Item.toString(items));
        System.out.println("End");
    }

    private static Item createItem(String s) {
        Item item = new Item();
        item.setS(s);
        return item;
    }

}

class Item {

    private String s;

    public String getS() {
        return s;
    }

    public void setS(String s) {
        this.s = s;
    }

    @Override
    public String toString() {
        return "Item: " + s;
    }

    public static String toString(Collection<Item> items) {
        String s = "";
        for(Item item : items) {
            s += item + "\n";
        }
        return s;
    }    

}

class ItemComparator implements Comparator<Item> {

    @Override
    public int compare(Item item1, Item item2) {
        return item1.getS().compareTo(item2.getS());
    }

}

答案 2 :(得分:0)

 public class MyComparable implements Comparator<Table>{
   @Override
   public int compare(Table table1, Table table2) {
    return (table1.getTableName().compareTo(table2.getTableName());
   }
 }

确保您已在表类中重写了hashcode和equals以实现此目的。