Skip to content

Instantly share code, notes, and snippets.

@salimchami
Last active November 22, 2022 20:43
Show Gist options
  • Select an option

  • Save salimchami/ad21d681ecc611da7d2db8f411f7910c to your computer and use it in GitHub Desktop.

Select an option

Save salimchami/ad21d681ecc611da7d2db8f411f7910c to your computer and use it in GitHub Desktop.
Objects Collections Diff in Java
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
/**
* A diff compares a 'base' collection with a 'next' collection.
* The diff with calculate items added and removed from the base collection based on a user-provided key extractor.
* Items that have been neither added or removed are returned as a list of {@link Change}s
* with the pair of the 'base' item and the 'next' item.
*
* @param <K> type of the key used to compare items
* @param <T> type of items to compare
*/
public class Diff<K, T> {
private final Function<T, K> keyMapper;
private final Collection<T> base;
private Collection<T> added;
private Collection<T> removed;
private Collection<Change<T>> changed;
public Diff(Collection<T> base, Function<T, K> keyExtractor) {
this.keyMapper = keyExtractor;
this.base = base;
}
public void with(List<T> next) {
Map<K, T> baseMap = base.stream().collect(toMap(keyMapper, identity()));
changed = next.stream()
.filter(n -> baseMap.containsKey(keyMapper.apply(n)))
.map(n -> new Change<>(baseMap.get(keyMapper.apply(n)), n))
.collect(toSet());
added = next.stream()
.filter(n -> !baseMap.containsKey(keyMapper.apply(n)))
.collect(toSet());
Set<K> nextKeys = next.stream().map(keyMapper).collect(toSet());
baseMap.keySet().removeAll(nextKeys);
removed = baseMap.values();
}
public Collection<T> added() {
return added;
}
public Collection<T> removed() {
return removed;
}
public Collection<Change<T>> changed() {
return changed;
}
public static final class Change<T> {
public final T base;
public final T next;
private Change(T base, T next) {
this.base = base;
this.next = next;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment