Examples
These examples show the most common ways to use Hermes.
Detect Updates in a Collection
Use CollectionItemChangeDetector when order does not matter.
This detector reports inserted, removed, and updated items, but it does not report moves.
import com.irurueta.hermes.CollectionItemChangeAction;
import com.irurueta.hermes.CollectionItemChangeDetector;
import com.irurueta.hermes.UpdatedCollectionItemChange;
import java.util.List;
record User(long id, String displayName, boolean active) { }
var oldUsers = List.of(
new User(1, "Ada", true),
new User(2, "Grace", true));
var newUsers = List.of(
new User(1, "Ada Lovelace", true),
new User(2, "Grace", true));
var detector = new CollectionItemChangeDetector<User>(
(left, right) -> left.id() == right.id(),
(left, right) -> left.displayName().equals(right.displayName())
&& left.active() == right.active());
var changes = detector.detectChanges(newUsers, oldUsers);
for (var change : changes) {
if (change.getAction() == CollectionItemChangeAction.UPDATED) {
var updated = (UpdatedCollectionItemChange<User>) change;
System.out.println(updated.getOldItem() + " -> " + updated.getNewItem());
}
}
Classes used in this example:
| Class | Source | Javadoc |
|---|---|---|
|
||
|
||
|
Replay Sequential List Changes
Sequential detectors are a good fit when you want to apply the returned operations to an existing ordered list.
import com.irurueta.hermes.InsertedListItemChange;
import com.irurueta.hermes.ListItemChange;
import com.irurueta.hermes.MovedListItemChange;
import com.irurueta.hermes.RemovedListItemChange;
import com.irurueta.hermes.SequentialListItemChangeDetector;
import com.irurueta.hermes.UpdatedListItemChange;
import java.util.ArrayList;
import java.util.List;
record Row(String id, String label) { }
var oldRows = List.of(
new Row("a", "Alpha"),
new Row("b", "Beta"),
new Row("c", "Gamma"));
var newRows = List.of(
new Row("c", "Gamma"),
new Row("b", "Beta v2"),
new Row("d", "Delta"));
var detector = new SequentialListItemChangeDetector<Row>(
(left, right) -> left.id().equals(right.id()),
(left, right) -> left.label().equals(right.label()));
var changes = detector.detectChanges(newRows, oldRows);
var working = new ArrayList<>(oldRows);
for (ListItemChange change : changes) {
switch (change.getAction()) {
case REMOVED -> {
var removed = (RemovedListItemChange<Row>) change;
working.remove(removed.getOldPosition());
}
case INSERTED -> {
var inserted = (InsertedListItemChange<Row>) change;
working.add(inserted.getNewPosition(), inserted.getNewItem());
}
case MOVED -> {
var moved = (MovedListItemChange<Row>) change;
var row = working.remove(moved.getOldPosition());
working.add(moved.getNewPosition(), row);
}
case UPDATED -> {
var updated = (UpdatedListItemChange<Row>) change;
working.set(updated.getPosition(), updated.getNewItem());
}
}
}
Classes used in this example:
| Class | Source | Javadoc |
|---|---|---|
|
||
|
||
|
||
|
||
|
||
|
Use Comparable Items
When items implement ComparableItem, Hermes can use the item methods directly.
import com.irurueta.hermes.ComparableItem;
import com.irurueta.hermes.ComparableCollectionItemChangeDetector;
record Account(String number, String owner, String status)
implements ComparableItem<Account> {
@Override
public boolean equals(Object other) {
return other instanceof Account account
&& number.equals(account.number);
}
@Override
public int hashCode() {
return number.hashCode();
}
@Override
public boolean equalContent(Account other) {
return owner.equals(other.owner) && status.equals(other.status);
}
}
var detector = new ComparableCollectionItemChangeDetector<Account>();
var changes = detector.detectChanges(newAccounts, oldAccounts);
The important rule is that equals(Object) identifies the same logical item.
It should not compare every field if those fields are supposed to produce UPDATED changes.
Classes used in this example:
| Class | Source | Javadoc |
|---|---|---|
|
||
|