由于逻辑错误,允许树集的值相同。

问题描述 投票:0回答:2

你好,我大家我现在正在学习java集合,有这样的作业。我的逻辑出了点问题,谁能告诉我我哪里出了问题?这是我的代码。

这是Family类,在这个类中,我实例化了母类的treeSet。

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class Family {
    Mother mom = new Mother("0", 0, 0);

    Set<Mother> Mothers = new TreeSet<Mother>(new Comparator<Mother>() {
        public int compare(Mother a, Mother b) {
            if(a.getName().compareTo(b.getName()) == 0) return 0;

            if(a.getMonth() == b.getMonth()){
                if(a.getDay() > b.getDay()) return 1;

                else if(a.getDay() < b.getDay()) return -1;
            }
            if(a.getMonth() > b.getMonth()) return 1;

            if(a.getMonth() < b.getMonth()) return -1;

            return a.getName().compareTo(b.getName());
        }
    });

    public Family(){}

    public boolean addMother(java.lang.String name, int day, int month)
    {
        Mother a = new Mother(name, day, month);
        return Nieces.add(a);
    }
}

这是Main类,我把母亲的TreeSet分配在这里。

public class Main {
    public static void main(String[] args) {
       Family myFam = new Family();
       myFam.addMother("Tokyo", 1, 3);
       myFam.addMother("Shaline", 1, 1);
       myFam.addMother("Betty", 2, 3);
       myFam.addMother("Amy", 1, 1);
       myFam.aaddMother("Shaline", 4, 3);
       System.out.println(myFam.Mothers);
    }
}

所以我想按照日期和月份来排序,我得到的输出是......。[Amy, Shaline, Tokyo, Betty, Shaline],这是真的,因为它是根据日期和月份排序的,但我希望它只有一个Shaline,因为它是一个TreeSet。我可以做些什么,使输出可以是 。Amy, Shaline, Tokyo, Betty]。我也已经尝试过像 if(a.getName().equals(b.getName())) return 0;

但是还是不行.谢谢大家的帮助!

java collections comparator treeset
2个回答
3
投票

你的比较器不一致。请看 比较国合同:

实现者还必须确保该关系是反身的。 ((compare(x, y)>0) && (compare(y, z)>0)) 意味着 compare(x, z)>0.

你的比较器违反了这一点,因为当 x"Shaline", 1, 1y"Betty", 2, 3z"Shaline", 4, 3,它正在报告 x < yy < z 使用月或日,所以转折性规则将要求 x < z但你的比较器报告 x == z 由于名称相同,返回零。

TreeSet 依赖于反转性,因为它允许高效的查找,不是将每个元素与插入的新元素进行比较,而是使用顺序导航到树中的正确位置。

你可以添加一个线性搜索,比如在 本回答但这样一来,就失去了 Set 因为它现在比较每一个包含的元素。

相反,我建议使用类似这样的方法。

Set<String> names = new HashSet<>();
Set<Mother> mothers = new TreeSet<>(Comparator.comparingInt(Mother::getMonth)
        .thenComparingInt(Mother::getDay).thenComparing(Mother::getName));

public Family(){}

public boolean addMother(java.lang.String name, int day, int month)
{
    return names.add(name) && mothers.add(new Mother(name, day, month));
}

这样可以简化并修复比较器,它现在一致地使用所有的 Mother 对象,并添加一个高效的预检。


1
投票

在添加时,只需检查新的母体是否是唯一的。

    public boolean addMother(java.lang.String name, int day, int month)
    {   
        for (Mother m: Mothers) {
            if (m.getName().equals(name)) {
                return false; // suppose the result should be false in case of not adding
            }
        }

        Mother a = new Mother(name, day, month);
        return Nieces.add(a);
    }
© www.soinside.com 2019 - 2024. All rights reserved.