Menu

Bug in Trove 3.0

Anonymous
2011-09-13
2012-09-24
  • Anonymous

    Anonymous - 2011-09-13

    Hi. I just moved from RC1 to 3.0, and I have found a problem. When using a
    custom strategy on byte arrays, the method equals om TCustomObjectHash is
    implemented as;

    @Override
    protected boolean equals( Object one, Object two ) {
    //noinspection unchecked
    return strategy.equals( ( T ) one, ( T ) two );
    }

    The problem, is that one of those two objects can be REMOVED, in which case
    the cast to T gives a ClassCastException. I have resolved it by overriding
    that method (see below) in my own class, but I thought you shhould know.

    @Override
    protected boolean equals( Object one, Object two ) {
    if (!(o1 instanceof byte)) return false;
    if (!(o2 instanceof byte)) return false;
    return strategy.equals( ( byte ) one, ( byte ) two );
    }

     
  • Anonymous

    Anonymous - 2011-09-13

    Here is a full class illustrating the problem. If you run it, it will fail
    with a ClassCastException. Thanks!


    package com.jt.jtp;

    import gnu.trove.map.hash.TCustomHashMap;
    import gnu.trove.strategy.HashingStrategy;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;

    public class TroveBug {

    private static byte random(int n, Random rnd) {
    byte ba = new byte;
    for (int i = 0; i < ba.length; i++) {
    ba_ = (byte)rnd.nextInt();
    }
    return ba;
    }

    private static class ByteArrayStrategy implements HashingStrategy<byte> { </byte>

    // Copied from Arrays.hashCode, but applied only to the first four bytes
    @Override
    public int computeHashCode(byte bytes) {
    if (bytes == null) return 0;
    int h = 1;
    for (int i = 0; i < 4; i++) h = 31 * h + bytes_;
    return h;
    }

    @Override
    public boolean equals(byte o1, byte o2) {
    return Arrays.equals(o1, o2);
    }
    }

    public static void main(String args) {
    Random rnd = new Random(1234);
    TCustomHashMap<byte, integer=""> map = new TCustomHashMap<byte, integer="">(new
    ByteArrayStrategy());
    List<byte> list = new ArrayList<byte>(); </byte></byte></byte,></byte,>

    for (int i = 0; i < 1000; i++) {
    byte ba = random(16, rnd);
    list.add(ba);
    map.put(ba, new Integer(i));
    }

    for (int i = 0; i < 1000; i++) {
    map.remove(list.get(i));
    }

    // Print all nulls!
    for (int i = 0; i < 1000; i++) {
    System.out.println(map.get(list.get(i)));
    }

    }

    }
    __

     
  • Rob Eden

    Rob Eden - 2011-09-13

    Thanks, I'll take a look right away.

    Rob

     
  • Johan Parent

    Johan Parent - 2011-09-13

    Patching TCustomObjectHash is probably easier than tightening the contract of
    HashStrategy by requiring to handle the REMOVED corner case. FREE should not
    happen, I quickly checked.

    Maybe simply:

    return  two != REMOVED && strategy.equals( ( T ) one, ( T ) two );
    

    I'll try later on

     
  • Johan Parent

    Johan Parent - 2011-09-19

    Hi,

    Confirming that the above proposed change fixes the reported issue. I'll
    commit it to svn as well as the problem scenario (in unittest)

    Johan

     

Log in to post a comment.