diff --git a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java
index b266c1caa9..68a55f5c8c 100644
--- a/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java
+++ b/src/main/java/org/apache/commons/text/similarity/DamerauLevenshteinDistance.java
@@ -16,6 +16,8 @@
*/
package org.apache.commons.text.similarity;
+import java.util.Objects;
+
/**
* An algorithm for measuring the difference between two character sequences using the
* Damerau-Levenshtein Distance.
@@ -32,7 +34,7 @@ public class DamerauLevenshteinDistance implements EditDistance {
private static int calculateCost(final SimilarityInput left, final SimilarityInput right, final int leftIndex, final int rightIndex,
final int[] curr, final int[] prev, final int[] prevPrev) {
- final int cost = left.at(leftIndex - 1) == right.at(rightIndex - 1) ? 0 : 1;
+ final int cost = Objects.equals(left.at(leftIndex - 1), right.at(rightIndex - 1)) ? 0 : 1;
// Select cheapest operation
int value = Math.min(
Math.min(
@@ -44,8 +46,8 @@ private static int calculateCost(final SimilarityInput left, final Simila
// Check if adjacent characters are the same -> transpose if cheaper
if (leftIndex > 1
&& rightIndex > 1
- && left.at(leftIndex - 1) == right.at(rightIndex - 2)
- && left.at(leftIndex - 2) == right.at(rightIndex - 1)) {
+ && Objects.equals(left.at(leftIndex - 1), right.at(rightIndex - 2))
+ && Objects.equals(left.at(leftIndex - 2), right.at(rightIndex - 1))) {
// Use cost here, to properly handle two subsequent equal letters
value = Math.min(value, prevPrev[rightIndex - 2] + cost);
}
diff --git a/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java b/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java
index 65f664bb57..a532ba31c7 100644
--- a/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java
+++ b/src/test/java/org/apache/commons/text/similarity/DamerauLevenshteinDistanceTest.java
@@ -77,7 +77,14 @@ static Stream limitedDamerauLevenshteinDistanceTestCases() {
Arguments.of("xyxyxyxyxy", "yxyxyxyxyx", 4, 2),
Arguments.of("aaaaabbbbbccccc", "cccccbbbbbaaaaa", 5, -1),
Arguments.of("thequickbrownfoxjumpsoverthelazydog", "thequickbrownfoxjumpsovrethelazydog", 1, 1),
- Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 3, 1)
+ Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 3, 1),
+ // Non-ASCII characters are outside the Character.valueOf cache, so identical inputs must still measure zero.
+ Arguments.of("caf\u00e9", "caf\u00e9", 1, 0),
+ Arguments.of("\u4f60\u597d", "\u4f60\u597d", 1, 0),
+ Arguments.of("na\u00efve", "na\u00efve", 1, 0),
+ // Transposing two adjacent non-ASCII characters costs one edit, exactly as it does for ASCII.
+ Arguments.of("caf\u00e9\u00e8", "caf\u00e8\u00e9", 1, 1),
+ Arguments.of("\u4f60\u597d", "\u597d\u4f60", 1, 1)
);
}
@@ -123,7 +130,16 @@ static Stream unlimitedDamerauLevenshteinDistanceTestCases() {
Arguments.of("xyxyxyxyxy", "yxyxyxyxyx", 2),
Arguments.of("aaaaabbbbbccccc", "cccccbbbbbaaaaa", 10),
Arguments.of("thequickbrownfoxjumpsoverthelazydog", "thequickbrownfoxjumpsovrethelazydog", 1),
- Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 1)
+ Arguments.of("antidisestablishmentarianism", "antidisestablishmentarianisn", 1),
+ // Non-ASCII characters are outside the Character.valueOf cache, so identical inputs must still measure zero.
+ Arguments.of("caf\u00e9", "caf\u00e9", 0),
+ Arguments.of("\u4f60\u597d", "\u4f60\u597d", 0),
+ Arguments.of("na\u00efve", "na\u00efve", 0),
+ Arguments.of("\ud83d\ude00", "\ud83d\ude00", 0),
+ // Transposing two adjacent non-ASCII characters costs one edit, exactly as it does for ASCII.
+ Arguments.of("caf\u00e9\u00e8", "caf\u00e8\u00e9", 1),
+ Arguments.of("\u4f60\u597d", "\u597d\u4f60", 1),
+ Arguments.of("\u00e9x", "x\u00e9", 1)
);
}