Collections
TreeSet: Comparatorが0を返す値は同じ要素として扱う
TreeSet は equals ではなく Comparator の比較結果で、要素の重複と検索を判断します。
SourceComparatorEquivalence.java
Java 21
package examples.sortedset;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public final class ComparatorEquivalence {
private ComparatorEquivalence() {}
public static Set<String> uniqueByLength(String... values) {
var words = new TreeSet<String>(Comparator.comparingInt(String::length));
for (var value : values) {
words.add(value);
}
return words;
}
}TestComparatorEquivalenceTest.java
Java 21
package examples.sortedset;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import org.junit.jupiter.api.Test;
class ComparatorEquivalenceTest {
@Test
void comparatorが0を返す異なる値はTreeSetで同じ要素として扱われる() {
var words = ComparatorEquivalence.uniqueByLength("cat", "dog", "java");
assertEquals(List.of("cat", "java"), List.copyOf(words));
assertEquals(2, words.size());
}
@Test
void comparatorが0を返す値は登録していなくてもcontainsで見つかる() {
var words = ComparatorEquivalence.uniqueByLength("cat");
assertTrue(words.contains("dog"));
}
}01Assertion
このテストで確認できること
- 文字列の長さだけを比較する Comparator では、同じ長さの別の文字列を重複として扱う
- 登録していない同じ長さの文字列も contains で見つかる
TreeSet と TreeMap は compare が 0 を返すキーを同じものとして扱います。equals と異なる比較規則を使うと、集合の要素数や検索結果が直感とずれるため、Comparator の等価性を設計として明示します。
OBSERVED RESULT
expected: [cat, java]
actual: [cat, java]
expected: contains("dog") → true
actual: true