简体   繁体   中英

java.util.treemap gives strange results

I have the following method :

     public final NavigableSet<AnimalCard> getCowTradeCardsSorted() {
    TreeMap<AnimalCard,AnimalCard> ssa = new TreeMap<AnimalCard,AnimalCard>();
    Iterator<E> i = this.cowTradeCards.iterator();
    System.out.println("Input is:"+this.cowTradeCards.toString());
    while (i.hasNext()) {
        E a = i.next();
        System.out.println("Adding 2 ssa:"+a.toString());

        ssa.put((AnimalCard) a ,(AnimalCard) a); //this.getCountOfOneCard(a));
        System.out.println("ssa is now"+ssa.toString());

    }
    System.out.println("returnvalue is"+ ssa.descendingKeySet().toString());
    return ssa.descendingKeySet().descendingSet();
}

where i would expect the following output as returnvalue: [1000,500,160,10]

but i get [1000]

here is the output fom console:

   Input is:[1000, 10, 160, 500]
   Adding 2 ssa:1000
   ssa is now{1000=1000}
   Adding 2 ssa:10
   ssa is now{1000=10}
   Adding 2 ssa:160
   ssa is now{1000=160}
   Adding 2 ssa:500
   ssa is now{1000=500}
   returnvalue is[1000]

what is wrong? it looks like treemap is binding all value to the first key?

ps: this.cowtradecards is a arraylist but that doesn´t matter really

    public class AnimalCard extends Card { ..........

      // super has this :public int getValue() {
  //        return this.value;
  //       }


    @Override
public int compareTo(Object o) {
    // Pufferelement vom Typ AnimalCard
    AnimalCard buffer;

    // Kontrolle, ob übergebenes Objekt vom Typ "AnimalCard" ist
    if (o instanceof MoneyCard) {   <--------------- here is the error !!!!! should be AnimalCard !
        // wenn ja, dann Typcasting vornehmen
        buffer = (AnimalCard) o;

        if (super.getValue() < buffer.getValue()) {
            return -1;
        }
        if (super.getValue() > buffer.getValue()) {
            return 1;
        }
        return 0;
    } else {
        // not an "AnimalCard"

    }
    return 0;
}

after i fixed the compareto:
    Input is:[1000, 10, 160, 500]
    Adding 2 ssa:1000
    ssa is now{1000=1000}
    Adding 2 ssa:10
    ssa is now{10=10, 1000=1000}
    Adding 2 ssa:160
    ssa is now{10=10, 160=160, 1000=1000}
    Adding 2 ssa:500
    ssa is now{10=10, 160=160, 500=500, 1000=1000}
    returnvalue is[1000, 500, 160, 10]

The problem likely has to do with compareTo in AnimalCard . Check that compareTo is doing what you expect it to do, and that two AnimalCard instances with different numbers are not considered equal based on this method (ie it does not return 0 in such cases). If they are, then that would explain your result, since TreeMap would simply update the pre-existing entry instead of adding a new one.

Also, if you're debugging, you might want to print the return value of put() (it could give you some insight as to what's going on).

Your toString method is saying "ssa is now{1000=1000}" and "ssa is now{1000=160}" - so probably, they all seem to have, for whatever reason, that 1000 in all of them. I would look at your compareTo method on AnimalCard for further clues.

Based on your method name, you want to sort your ArrayList(and remove duplicates). If AnimalCard implements Comarable, this should be as simple as

return new TreeSet<AnimalCard>(cowTradeCards);

As everyone else has been saying, you've got an incorrect/incomplete implementation of compareTo() , and it's causing the problems you're seeing.

public int compareTo(Object o) {
    // Pufferelement vom Typ AnimalCard
    AnimalCard buffer;

    // Kontrolle, ob übergebenes Objekt vom Typ "AnimalCard" ist
    if (o instanceof MoneyCard) {   <--------------- here is the error !!!!! should be AnimalCard !
        // Lots of really interesting logic that's never going to get run because o instanceof AnimalCard, not Moneycard.
    } else {
        // We're always going to come here, but we're not going to do anything, so we'll fall through...
    }
    // And now we'll return a value saying that the two objects are equal.  ALWAYS.
    return 0;
}

Your comparator says that all AnimalCards are equal to one another. Your TreeMap adds the first one (1000) as you would expect. When it comes to the second one, it recognizes that it's equal to the first one, so it keeps the key as is but puts the new AnimalCard into the value. (Why, I'm not sure, but it doesn't really matter.) When we insert the third one, the same thing happens: the first object is kept as the key, and the third replaces the second as the value. So after inserting them all, you're left with a map with a single entry, with a key equal to the first and a value equal to the second.

To beat a dead horse: Fix your compareTo() . You'll fix your problem.

Incidentally, the sample code you've posted doesn't need a TreeMap; if you're using the value as the key, what you really wanted was probably a Treeset .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM