Choosing a Detector
Hermes offers detector classes for three decisions:
-
Whether the input is position-aware.
-
Whether items implement
ComparableItem. -
Whether list positions should be absolute or sequential.
Decision Tree
Detector Matrix
| Collection shape | Item comparison style | Position style | Use |
|---|---|---|---|
Collection, set, map values, or any position-independent data |
Custom comparators |
Not applicable |
|
Collection, set, map values, or any position-independent data |
Items implement |
Not applicable |
|
List or other ordered data |
Custom comparators |
Absolute positions |
|
List or other ordered data |
Items implement |
Absolute positions |
|
List or other ordered data |
Custom comparators |
Sequential edit positions |
|
List or other ordered data |
Items implement |
Sequential edit positions |
|
Custom Comparators
Use comparator-based detectors when your item type cannot or should not implement Hermes interfaces. The identity comparator answers "is this the same logical item?" The content comparator answers "does this same logical item have the same content?"
var detector = new CollectionItemChangeDetector<Product>(
(left, right) -> left.id().equals(right.id()),
(left, right) -> left.name().equals(right.name())
&& left.price().compareTo(right.price()) == 0);
ComparableItem
Use comparable detectors when the item type can carry its own comparison rules.
equals(Object) must represent identity, not full content equality.
equalContent(T other) represents content equality.
import com.irurueta.hermes.ComparableItem;
record Product(String id, String name, int quantity)
implements ComparableItem<Product> {
@Override
public boolean equals(Object other) {
return other instanceof Product product && id.equals(product.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equalContent(Product other) {
return name.equals(other.name) && quantity == other.quantity;
}
}
After that, detector construction is simpler:
var detector = new ComparableListItemChangeDetector<Product>();
var changes = detector.detectChanges(newProducts, oldProducts);
Absolute vs Sequential List Positions
ListItemChangeDetector and ComparableListItemChangeDetector report positions with respect to the old and new lists.
This is useful when you want to describe what changed between two snapshots.
SequentialListItemChangeDetector and ComparableSequentialListItemChangeDetector report positions as if changes are applied in returned order to the old list.
This is useful when you want to replay the changes against an existing list.
For a simple swap from [A, B] to [B, A], the absolute detector reports both items as moved.
The sequential detector can report a single move that transforms the old list into the new list.