How do I check if a BigDecimal is in a Set or Map in a scale independent way?

StackOverflow https://stackoverflow.com/questions/20091723

  •  02-08-2022
  •  | 
  •  

質問

BigDecimal's equals() method compares scale too, so

new BigDecimal("0.2").equals(new BigDecimal("0.20")) // false

It's contested why it behaves like that.

Now, suppose I have a Set<BigDecimal>, how do I check if 0.2 is in that Set, scale independent?

Set<BigDecimal> set = new HashSet<>();
set.add(new BigDecimal("0.20"));
...
if (set.contains(new BigDecimal("0.2")) { // Returns false, but should return true
    ...
}
役に立ちましたか?

解決

contains() will work as you want it to if you switch your HashSet to a TreeSet.

It is different from most sets as it will decide equality based on the compareTo() method as opposed to equals() and hashCode():

a TreeSet instance performs all element comparisons using its compareTo (or compare) method

And since BigDecimal.compareTo() compares without regard to scale, that's exactly what you want here.

Alternatively you could ensure that all elements in the Set are of the same, minimal scale, by always using stripTrailingZeros (both on add() and on contains()):

set.add(new BigDecimal("0.20").stripTrailingZeros());
...
if (set.contains(new BigDecimal("0.2").stripTrailingZeros()) {
  ...
}

他のヒント

HashSet#contains method can't serve your requirement, it implicitly call equals method. You should iterate over Set and use compareTo method. If value is found than set a flag.

    Set<BigDecimal> set = new HashSet<>();
    set.add(new BigDecimal("0.20"));
    boolean found=false;
    for (BigDecimal bigDecimal : set) {
        if(bigDecimal.compareTo(new BigDecimal("0.2"))==0){
            System.out.println("Value is contain");
            found=true;
            break;
        }
    }
    if(found)// Use this flag for codition.

Use the compareTo method of BigDecimal.

BigDecimal("0.200").compareTo(new BigDecimal("0.2")) == 0; // Means they are equal.

From the JavaDoc

Compares this BigDecimal with the specified BigDecimal. Two BigDecimal objects that are equal in value but have a different scale (like 2.0 and 2.00) are considered equal by this method. This method is provided in preference to individual methods for each of the six boolean comparison operators (<, ==, >, >=, !=, <=). The suggested idiom for performing these comparisons is: (x.compareTo(y) <op> 0), where <op> is one of the six comparison operators.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top