使用自定义比较器

Using a custom comparator

我查了一堆类似的问题,但还是很困惑。无论如何,这是一项已经过去的任务。

我有礼物class:

public class Present implements PresentInterface{

private String name;
private String type;
private double cost;

public Present() {   
}

public Present(String name, String type, double cost) {
    this.name = name;
    this.type = type;
    this.cost = cost;
} 

然后是一堆用于获取和设置值的代码。
我有一个 Child class,其中包含关于 child.
的一堆信息 我有一个 GiftList class,它是一个礼物数组列表。每个礼物列表最多关联一个 child.
然后我有一个 GiftSelector class,它是 GiftLists 的数组列表。
我想在 giftSelector class 中有一个方法,它创建一个 hashmap,键是 children,值是按成本排序的礼物列表。
到目前为止我有:

    public HashMap<Child, ArrayList<Present>> sortList(){

    HashMap<Child, ArrayList<Present>> presentMap = new HashMap<Child, ArrayList<Present>>();
    ArrayList<Present> presentList = new ArrayList<Present>();

    for (GiftList giftList : giftSelector){
        presentList.clear();//clears the present list with each iteration otherwise 
        //each child would be paired with a list of presents containing those 
        //of the child before.

        Child mapChild = giftList.getChild();

        for (Present present : giftList.getAllPresents()){
            presentList.add(present);//goes through each present in the giftlist and adds it to presentlist
        }

        Collections.sort(presentList, new Comparator<Present>());

        presentMap.put(mapChild, presentList);
    }
    return presentMap;
}
}

没有定义比较器,所以它当然不起作用。我是在 Present class 或 giftSelector class 中定义比较器,还是给它一个全新的 class 自己的?
我想我在某个地方需要这样的东西:

public int compare(Present p1, Present p2){
    if (p1==null || p2 == null){
        return 0;
    }
    return p1.getCost().compareTo(p2.getCost());
}

然后是一些涉及覆盖和设置 compareTo 值以及其他魔法的东西。任何建议将不胜感激:)

顺便说一句,当我取出 sortList() 方法的 Collections.sort(presentList, comparator) 位时,它编译并运行良好,除了 presentMap 中的每个 child 具有相同的价值。他们都有一个数组列表,其中包含迭代的最后一个礼物列表的礼物。不过,我可能错过了一些明显的东西。

我会将其定义为静态成员class:

public class Present implements PresentInterface {
    public static class CostComparator implements Comparator<Present >
    {
        public int compare(Present p1, Present p2)
        {
            // use either this line for null
            if (p1 == null || p2 == null) throw new NullPointerException();
            // or these 2 lines for null:
            if (p1 == null) return p2 == null ? 0 : -1;
            if (p2 == null) return 1;
            // and now do a reference check for speed
            if (p1 == p2) return 0;
            // and finally the value checks
            return Double.compare(p1.cost, p2.cost);
        }
    }
    private String name;
    private String type;
    private double cost;
}

null 排序有两种选择(如图所示),如 per the docs:

Unlike Comparable, a comparator may optionally permit comparison of null arguments, while maintaining the requirements for an equivalence relation

把它放在 Present class 里面只是为了方便查找,而且因为它只与 Present class 相关所以嵌套它是有意义的.但是,我会将其与 equals 的不一致记录为 according to the docs:

Caution should be exercised when using a comparator capable of imposing an ordering inconsistent with equals to order a sorted set (or sorted map).

即由于它现在对 equals 有不同的 "natural order" 定义,您可能 运行 在各种情况下遇到无法预料的问题。

您还应该考虑如何订购具有相同成本的两个不同的 Present 对象 - 您需要做的就是按成本订购吗?

后期编辑就你的"second question"而言,每次启动迭代器时都需要实例化一个新的ArrayList,否则每个映射值都指向相同的arraylist(更多解释见):

for (GiftList giftList : giftSelector){
    presentList = new ArrayList<Present>; // create a new instance of a present list with each iteration otherwise ...