简体   繁体   中英

TreeMap with own comparator implementation

Everyone.

I write a TreeMap with an own implementation of method compare() .

The aim is to sort the keys of the map in order: entries with less time and less values of bit should be on top. All entries have unique time. I want to choose between objects with bit: false - choose objects with less time.

But the following Java code restricts me to add some new entries.

private TreeMap<Entry<K>,V>  map = new TreeMap<Entry<K>,V>(new Comparator<Entry<K>>() {

  @Override
  public int compare(Entry<K> entry1, Entry<K> entry2) {

    int time1 = entry1.getTime();        
    int time2 = entry2.getTime();

    boolean bit1 = entry1.isBit();
    boolean bit2 = entry2.isBit();

    if (time1 < time2) {
      if ( (bit1 == false && bit2 == true)
        || (bit1 == false && bit2 == false)
        || (bit1 == true && bit2 == true))
        return -1;
    } else if (time1 > time2) {
      if ( (bit1 == true && bit2 == false)
        || (bit1 == true && bit2 == true)
        || (bit1 == false && bit2 == false))
        return 1;
    }

    return 0;
  }

});

Can anyone please explain why?

Ps I added entry's with keys: 1, 2, 3, 4, 5. Then I tried to add entry with key 4, and It was not added. Key 1, 2 .. - it means i create entry with 3 fields: key, bit(false - default), time(unique value created by counter). So all entry's im my opninion were unique.

This is entry class:

public class Entry<K> {

private K id;
private boolean bit;
private int time;

public Entry(K id, Boolean bit, int time) {

    this.setId(id);
    this.setBit(bit);
    this.setTime(time);

}

public K getId() {
    return id;
}

public void setId(K id) {
    this.id = id;
}

public boolean isBit() {
    return bit;
}

public void setBit(boolean bit) {
    this.bit = bit;
}

public int getTime() {
    return time;
}

public void setTime(int time) {
    this.time = time;
}

public boolean equals(Object o){
    if (this.id == ((Entry)o).getId()){
        return true;
    }
    return false;
}   
}

And in such way I add new entrys:

public void put(K key, V value){
    entry = new Entry<K>(key, false, clock++);
    if (map.size() < initialCapacity){
        map.put(entry, value);
    } else {
        if (this.get(key) == null) {
            map.remove(map.firstEntry().getKey());
            map.put(entry, value);
        }
    }           
}

public V get(K key){
    Iterator it = map.keySet().iterator();
    while (it.hasNext()){
        Entry entry = (Entry) it.next();
        if (key.equals(entry.getId())){
            entry.setBit(true);
            return map.get(entry);
        }
    }       
    return null;
}

Running code:

ClockCacheMaximus<BigInteger, Object> ccm = new ClockCacheMaximus<BigInteger, Object>(3);;
    ccm.put(new BigInteger("1"), "aaa");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("2"), "bbb");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("3"), "ccc");
    System.out.println("map" + ccm.getAll());   
    System.out.println();
    ccm.put(new BigInteger("4"), "ddd");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("5"), "www");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("4"), "rrr");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("6"), "rrr");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("7"), "rrr");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("8"), "rrr");
    System.out.println("map" + ccm.getAll());
    System.out.println();
    ccm.put(new BigInteger("9"), "rrr");
    System.out.println("map" + ccm.getAll());

Result:

Entry: key = 1; bit = false; time = 0; Value = aaa ---put because of norm size: aaa map[1]

Entry: key = 2; bit = false; time = 1; Value = bbb ---put because of norm size: bbb map[1, 2]

Entry: key = 3; bit = false; time = 2; Value = ccc ---put because of norm size: ccc map[1, 2, 3]

Entry: key = 4; bit = false; time = 3; Value = ddd ---put with remove map[2, 3, 4]

Entry: key = 5; bit = false; time = 4; Value = www ---put with remove map[3, 4, 5]

Entry: key = 4; bit = false; time = 5; Value = rrr !object was found map[3, 4, 5]

Entry: key = 6; bit = false; time = 6; Value = rrr ---put with remove map[4, 5]

Entry: key = 7; bit = false; time = 7; Value = rrr ---put because of norm size: rrr map[4, 5]

Entry: key = 8; bit = false; time = 8; Value = rrr ---put because of norm size: rrr map[4, 5]

Entry: key = 9; bit = false; time = 9; Value = rrr ---put because of norm size: rrr map[4, 5]

TreeMap uses only comparator to check uniqueness.
If you have 2 keys that are equal according to your comparator then one of them will not be added to map. See SortedMap :

Note that the ordering maintained by a sorted map (whether or not an explicit comparator is provided) must be consistent with equals if the sorted map is to correctly implement the Map interface. (See the Comparable interface or Comparator interface for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a tree map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.

In your opinion keys are unique (and they unique if you check with equals) but TreeMap uses only comparator to check uniqueness.

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