You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Ruiqi Dong (Jira)" <ji...@apache.org> on 2026/05/21 10:14:00 UTC
[jira] [Created] (MATH-1689) Frequency.equals()/hashCode() ignores the comparator
Ruiqi Dong created MATH-1689:
--------------------------------
Summary: Frequency.equals()/hashCode() ignores the comparator
Key: MATH-1689
URL: https://issues.apache.org/jira/browse/MATH-1689
Project: Commons Math
Issue Type: Bug
Components: legacy
Reporter: Ruiqi Dong
*Summary*
Frequency behavior depends on the comparator used by its internal map, but equals() and hashCode() ignore that comparator. Two Frequency objects with different ordering semantics can therefore compare equal.
*Affected code*
File: commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/stat/Frequency.java
{code:java}
public long getCumFreq(T v) {
...
Comparator<? super T> c = freqTable.comparator();
if (c == null) {
c = new NaturalComparator<>();
}
...
}
public List<T> getMode() {
...
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((freqTable == null) ? 0 : freqTable.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
...
Frequency<?> other = (Frequency<?>) obj;
return freqTable.equals(other.freqTable);
} {code}
*Reproducer*
Add the following test to commons-math-legacy/src/test/java/org/apache/commons/math4/legacy/stat/FrequencyTest.java:
{code:java}
@Test
public void testEqualsShouldConsiderComparator() {
Frequency<Integer> ascending = new Frequency<>();
Frequency<Integer> descending = new Frequency<Integer>(Comparator.reverseOrder());
ascending.addValue(1);
ascending.addValue(2);
descending.addValue(1);
descending.addValue(2);
Assert.assertEquals(1, ascending.getCumFreq(1));
Assert.assertEquals(2, descending.getCumFreq(1));
Assert.assertEquals("[1, 2]", ascending.getMode().toString());
Assert.assertEquals("[2, 1]", descending.getMode().toString());
Assert.assertNotEquals(ascending, descending);
} {code}
Run:
{code:java}
mvn -q -pl commons-math-legacy -Dtest=org.apache.commons.math4.legacy.stat.FrequencyTest test {code}
Observed behavior:
{code:java}
FrequencyTest.testEqualsShouldConsiderComparator:223
Values should be different. Actual:
Value Freq. Pct. Cum Pct.
2 1 50% 50%
1 1 50% 100% {code}
Expected behavior:
Frequencies with different comparators should not compare equal when their observable ordering behavior differs.
The comparator affects at least getCumFreq() and getMode(). Since those outputs differ, equality and hashing should not ignore the comparator.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)