Last active
November 22, 2022 20:43
-
-
Save salimchami/ad21d681ecc611da7d2db8f411f7910c to your computer and use it in GitHub Desktop.
Objects Collections Diff in Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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