Created
June 10, 2015 21:29
-
-
Save Groxx/2f1033947b3ba169729d to your computer and use it in GitHub Desktop.
"find differences between data sets X and Y" helper
This file contains 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
public class Diff<Type> { | |
public interface Finder<Type> { | |
/** Return true to denote a "represents the same thing" match (do not compare contents) */ | |
boolean find(Type left, Type right); | |
} | |
public interface Equality<Type> { | |
boolean equals(Type left, Type right); | |
} | |
private final Finder<Type> finder; | |
private final Equality<Type> detector; | |
private final List<Type> added = new ArrayList<>(); | |
private final List<Type> removed = new ArrayList<>(); | |
private final List<Pair<Type, Type>> changed = new ArrayList<>(); | |
public Diff(Finder<Type> finder, Equality<Type> detector) { | |
this.finder = finder; | |
this.detector = detector; | |
} | |
public void populate(List<Type> left, List<Type> right) { | |
// TODO: ok, so not strictly correct. | |
ASSERT(isEmpty(), "Must not have populated already"); | |
List<Type> rightCopy = new ArrayList<>(right); | |
for (Type l : left) { | |
Type found = null; | |
for (Iterator<Type> i = rightCopy.iterator(); i.hasNext(); ) { | |
Type r = i.next(); | |
if (finder.find(l, r)) { | |
found = r; | |
i.remove(); | |
break; | |
} | |
} | |
if (found == null) { | |
removed.add(l); | |
} else if (!detector.equals(l, found)) { | |
changed.add(new Pair<>(l, found)); | |
} | |
} | |
for (Type r : rightCopy) { | |
added.add(r); | |
} | |
} | |
public List<Type> getAdded() { | |
return added; | |
} | |
public List<Type> getRemoved() { | |
return removed; | |
} | |
public List<Pair<Type, Type>> getChanged() { | |
return changed; | |
} | |
public boolean isEmpty() { | |
return added.isEmpty() && removed.isEmpty() && changed.isEmpty(); | |
} | |
} | |
// use: | |
Diff<Thing> diff = | |
new Diff<>( | |
// how to find equivalent things | |
(a,b) -> a.getId().equals(b.getId(), | |
// how to check for updates. | |
(a,b) -> a.latitude == b.latitude && | |
a.longitude == b.longitude && | |
a.speed = b.speed); | |
diff.populate(oldData, newData); | |
diff.getAdded() // returns all new ID things | |
diff.getRemoved() // returns all things that have disappeared | |
diff.getChanged() // returns Pair<old, new> so you can figure out how to handle each one |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment