admin管理员组

文章数量:1277286

I have a class that includes sets and optionals:

class SomeRequest{

   Set<Long> longs;
   Optional<String> name;
   Optional<Set<Long>> opLongs;
   Optional<Long> toBeIgnored;
   Collection<Field> fields

}

I'm looking for ways to compare two objects of the above class (where I have previously saved a hashcode of one object) but I want to ignore certain fields. Note that since this is only one use case, I don't want to override hashCode.

private int getParameterHash(SomeRequest req){
    SomeRequest newReq = new SomeRequest(
                          req.longs,
                          req.name,
                          req.opLongs,
                          null,    //because I want to ignore this for my use case
                          req.fields
                      );
    return newReq.hashCode();
}

I save this hash in db and then when I encounter the second object, I calculate this same hash and compare it with what I already have to ensure they're equal.

Questions:

  1. Is there a better way to do this?
  2. Set doesn't care about order (1st & 3rd fields) but Collection does (last field). So how can I make it ignore the order?

I have a class that includes sets and optionals:

class SomeRequest{

   Set<Long> longs;
   Optional<String> name;
   Optional<Set<Long>> opLongs;
   Optional<Long> toBeIgnored;
   Collection<Field> fields

}

I'm looking for ways to compare two objects of the above class (where I have previously saved a hashcode of one object) but I want to ignore certain fields. Note that since this is only one use case, I don't want to override hashCode.

private int getParameterHash(SomeRequest req){
    SomeRequest newReq = new SomeRequest(
                          req.longs,
                          req.name,
                          req.opLongs,
                          null,    //because I want to ignore this for my use case
                          req.fields
                      );
    return newReq.hashCode();
}

I save this hash in db and then when I encounter the second object, I calculate this same hash and compare it with what I already have to ensure they're equal.

Questions:

  1. Is there a better way to do this?
  2. Set doesn't care about order (1st & 3rd fields) but Collection does (last field). So how can I make it ignore the order?
Share Improve this question edited Feb 25 at 3:36 Basil Bourque 340k122 gold badges930 silver badges1.3k bronze badges asked Feb 25 at 1:42 S.DanS.Dan 1,9306 gold badges33 silver badges59 bronze badges 3
  • 1 1) You can get hash codes of required instance components separately and XOR the results. 2) Do the same to the Collection items, it will make the result independent from the order. Don't you think it will solve your problem? – Sergey A Kryukov Commented Feb 25 at 2:31
  • 6 This sounds like a bad idea. Hash codes are not guaranteed to be unique. They're supposed to be an optimization. – shmosel Commented Feb 25 at 3:30
  • Your two questions at the end are orthogonal. Each can be addressed without regard for the other. They should be two separate posts on Stack Overflow. – Basil Bourque Commented Feb 25 at 8:16
Add a comment  | 

2 Answers 2

Reset to default 2

If you were merely comparing objects in memory, define a Comparator.

But you said you need an actual hash code for a database lookup. To define an alternate hash code value while leaving in place the original hash code value, define an alternate hashCode method. Here we write a method named hashCodeIgnoringOneField.

For convenience, call Objects.hash.

class SomeRequest{
    Set<Long> longs;
    Optional<String> name;
    Optional<Set<Long>> opLongs;
    Optional<Long> toBeIgnored;
    Collection<Field> fields

    public int hashCodeIgnoringOneField 
    {
        // Omitting field: `Optional<Long> toBeIgnored`. 
        return Objects.hash ( this.longs , this.name , this.opLongs , this.fields ) ;
    }
}

However, as Commented, you should not be doing database lookups based on hash value alone. Hash codes are not meant to be unique. The premise of your Question is flawed: Hashing is not appropriate for comparing objects.

  1. Is there a better way to do this?

Assuming "this" means "compute a custom hash code", it is debatable if there is a better way.

However there are alternative ways. For example, if the custom hashcode is not going to be used for a key in a HashMap or HashSet or equivalent, you could simply define it as a new hash code method that ignores some of the fields.

I should note that you cannot assume that two objects (of the same type) are equal just because they have the same hash code. Hash codes are not unique.

Indeed, using hash codes doesn't necessarily make comparisons faster on average.

You need to do some careful analysis to determine if what you are doing is correct, and if it is correct whether it will improve performance.


  1. Set doesn't care about order but Collection does.

That depends on what the actual Collection class is. The hashcode of a collection may or may not be order sensitive.

So how can I make it ignore the order?

Assuming that it is order sensitive your case, you can replace the call to (say) fields.hashCode() with some code that iterates the elements of fields and computes the XOR of their hashcodes.

本文标签: javaComparing two objects using hashcodeStack Overflow