为什么Java TreeMap不打印所有插入的条目

时间:2016-04-02 14:16:32

标签: java string treemap comparable compareto

请告诉我这里发生了什么问题。我有一个Person类,我在TreeMap中使用它作为键。我也实现了Comparable,以便TreeMap可以进行排序。

public class Person implements Comparable{

private String name;
private int age;
// getters and setters were omitted
@Override
public int compareTo(Object o) {
    return 0;
}
}

现在我创建了TreeMap并在其中添加了值:

Map treeMap=new TreeMap<Person,Object>();

treeMap.put(new Person(), "String1");
treeMap.put(new Person(), "String2");
treeMap.put(new Person(), "String3");
treeMap.put(new Person(), "String4");

System.out.println(treeMap);

使用System.out.println(treeMap); Iam直接打印后,只获取最后插入的值,即

输出: {Person@4aa36c=String4}

我知道键应该是不同的但是新操作符总是创建一个新对象所以我认为它很好。但我无法弄清楚这里发生了什么问题。

4 个答案:

答案 0 :(得分:2)

您可能会向后放置Map中的项目,并且很可能希望将Person对象作为值,将String作为键。但首先,您需要使用构造函数增强Person对象,以允许您至少设置名称,也可以设置年龄。将构造函数添加到“Person”:

public Person(String n, int a){
   this.name = n;
   this.age = a;
}

然后,您可以重新排序向地图添加元素的方式:

 Person p1 = new Person("Bob Jones", 32);
 treeMap.put(p1.getName(), person);

此外,TreeMap使用compareTo方法确定将条目放在地图中的位置。因此,如果您打算使用Person对象作为键,则需要实现compareTo方法。但是你的compareTo方法没有正确实现,只是为每个元素返回0,导致你的元素覆盖Map中的每个其他位置:

@Override
public int compareTo(Object o) {
    / TODO Auto-generated method stub
    return 0;
}

您需要正确实现方法内容(因此TODO语句)。

可能会在Person类中添加社会安全号码(SSN):

Long ssn;

public void setSsn(Long value){
    ssn = value;
}

public Long getSsn(){
    return ssn;
}

然后你可以在ssn上进行比较:

@Override
public int compareTo(Object o) {
    if(o == null) return 1;
    Person op = (Person)o;
    return ssn.compareTo(op.getSsn());
}

但是如果你只是想用你所拥有的东西创建某种类型的组合,可以连接名称和年龄以尝试具有唯一性:

@Override
public int compareTo(Object o) {
    if(o == null) return 1;
    Person op = (Person)o;
    return (name + age).compareTo(op.getName() + op.getAge());
}

答案 1 :(得分:2)

您错误地覆盖了toCompare方法。它总是返回0。因此,树中的所有对象都将被解释为相同,而treeMap始终只包含最后添加的值。

我建议你考虑一下紧凑的(但不是一般的@ 4castle注意到的)解决方案。

@Override
public int compareTo(Person o) {
    if (age != o.age) return age > o.age ? 1 : -1;
    return name.compareTo(o.name);
}

如果您将类声明的第一行更改为

public class Person implements Comparable<Pesron>

答案 2 :(得分:2)

TreeMapcompareTo尝试将Comparable元素转换为{equals时使用Object put方法的Map方法1}}。由于compareTo方法实现会为所有0个对象返回Person,因此TreeMap中只能有一个元素。

因此,当您尝试放置多个Person个密钥时,TreeMap仅更新值,因为所有Person个对象都相同(根据您对compareTo的实现)

以下是来自Java-8

TreeMap.put的代码段
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    else {
        if (key == null)
            throw new NullPointerException();
        @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
        do {
            parent = t;
            cmp = k.compareTo(t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }

首先检查是否提供Comparator,如果是,TreeMap使用compare方法比较密钥,否则使用compareTo方法Comparable为了比较。

答案 3 :(得分:0)

根据内存地址,密钥并不是唯一的,它们基于具有唯一值而是唯一的。您的所有Person个对象几乎相同,但更重要的是,您的所有Person个对象声称是&#34;等于&#34;给定当前Person实现的任何其他compareTo对象(0表示相等)。

put方法的参数顺序首先是键,值是秒。您需要重新排列put语句,以便在前面有一些独特的内容(字符串),从而使所有条目都是唯一的。

treeMap.put("String1", new Person());
treeMap.put("String2", new Person());
treeMap.put("String3", new Person());
treeMap.put("String4", new Person());

现在无需在Comparable中实施compareToPerson方法。

如果您要求Person对象为密钥,则必须通过为其提供唯一变量来使每个变量唯一,以便使用compareTo方法正常。最佳解决方案是为每个Person对象添加所需的ID号,或者使用nameage作为对象的唯一值。将此代码添加到Person

private int id;
private static int numPeople = 0;
public Person() {
    numPeople++;
    id = numPeople;
    name = "";
}
@Override
public int compareTo(Person o) {
    if (age != o.age) return age > o.age ? 1 : -1;
    if (!name.equals(o.name) return name.compareTo(o.name);
    return id > o.id ? 1 : -1;
}

public class Person implements Comparable<Person>