Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCollectionsDifference.java
More file actions
Latest commit
125 lines (108 loc) · 4.51 KB
/
Copy pathCollectionsDifference.java
File metadata and controls
125 lines (108 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
packagemu.diff;
importcom.google.common.base.MoreObjects;
importcom.google.common.collect.Lists;
importjava.util.Collection;
importjava.util.List;
importjava.util.Objects;
importjava.util.Optional;
/**
* compare two collections and compute items difference
*
* usage: <code>CollectionsDifference.difference(left, right, itemMatcher)</code>
* ItemMatcher should return one of:
* None - the item (left, right) do not match
* Partial - the item match, but is not identical
* Exact - the item is a perfect match
*
*/
publicclassCollectionsDifference {
publicinterfaceItemMatch {}
publicstaticclassItemMatchers {
publicstaticfinalItemMatchExact = newItemMatchers.Exact();
publicstaticfinalItemMatchNone = newItemMatchers.None();
publicstaticclassExactimplementsItemMatch {}
publicstaticclassNoneimplementsItemMatch {}
publicstaticclassPartialimplementsItemMatch {
privatefinalintrank;
publicPartial() {
this(0);
}
publicPartial(intrank) {
this.rank = rank;
}
publicintgetRank() {
returnrank;
}
@Override
publicStringtoString() {
returnMoreObjects.toStringHelper(this)
.add("rank", rank)
.toString();
}
@Override
publicbooleanequals(Objecto) {
if (this == o) returntrue;
if (o == null || getClass() != o.getClass()) returnfalse;
Partialpartial = (Partial) o;
returnrank == partial.rank;
}
@Override
publicinthashCode() {
returnObjects.hash(rank);
}
}
}
publicinterfaceItemMatcher<L, R> {
ItemMatchmatch(Lleft, Rright);
}
publicstatic <L, R> CollectionsDifferenceImpl<L, R> difference(Collection<L> left, Collection<R> right, ItemMatcher<L, R> matcher) {
List<L> itemsOnlyOnLeft = Lists.newArrayList();
List<R> itemsOnlyOnRight = Lists.newArrayList();
List<ItemDifference<L, R>> itemsOnBothWithExactMatch = Lists.newArrayList();
List<ItemDifference<L, R>> itemsOnBothWithPartialMatch = Lists.newArrayList();
doDifference(left, right, matcher, itemsOnlyOnLeft, itemsOnlyOnRight, itemsOnBothWithExactMatch, itemsOnBothWithPartialMatch);
returnnewCollectionsDifferenceImpl<>(itemsOnlyOnLeft, itemsOnlyOnRight, itemsOnBothWithExactMatch, itemsOnBothWithPartialMatch);
}
privatestatic <L, R> voiddoDifference(Collection<L> left, Collection<R> right, ItemMatcher<L, R> matcher, List<L> itemsOnlyOnLeft, List<R> itemsOnlyOnRight, List<ItemDifference<L, R>> itemsOnBothWithExactMatch, List<ItemDifference<L, R>> itemsOnBothWithPartialMatch) {
List<L> itemsToProcessOnLeft = Lists.newArrayList(left);
List<R> itemsToProcessOnRight = Lists.newArrayList(right);
for (LleftItem : Lists.newArrayList(left)) {
Optional<R> rightItem = getItemByExactMatch(leftItem, itemsToProcessOnRight, matcher);
if (rightItem.isPresent()) {
itemsToProcessOnLeft.remove(leftItem);
itemsToProcessOnRight.remove(rightItem.get());
itemsOnBothWithExactMatch.add(newItemDifference<>(leftItem, rightItem.get()));
}
}
for (LleftItem : Lists.newArrayList(itemsToProcessOnLeft)) {
Optional<R> rightItem = getItemByPartialMatch(leftItem, itemsToProcessOnRight, matcher);
if (rightItem.isPresent()) {
itemsToProcessOnLeft.remove(leftItem);
itemsToProcessOnRight.remove(rightItem.get());
itemsOnBothWithPartialMatch.add(newItemDifference<>(leftItem, rightItem.get()));
}
}
itemsOnlyOnLeft.addAll(itemsToProcessOnLeft);
itemsOnlyOnRight.addAll(itemsToProcessOnRight);
}
privatestatic <R, L> Optional<R> getItemByExactMatch(Litem, Collection<R> collection, ItemMatcher<L, R> matcher) {
for (RitemToCompare : collection) {
if (matcher.match(item, itemToCompare) == ItemMatchers.Exact) {
returnOptional.of(itemToCompare);
}
}
returnOptional.empty();
}
privatestatic <R, L> Optional<R> getItemByPartialMatch(Litem, Collection<R> collection, ItemMatcher<L, R> matcher) {
intmaxRank = Integer.MIN_VALUE;
Optional<R> selectedItem = Optional.empty();
for (RitemToCompare : collection) {
ItemMatchmatchResult = matcher.match(item, itemToCompare);
if (matchResultinstanceofItemMatchers.Partial && ((ItemMatchers.Partial) matchResult).getRank() > maxRank) {
maxRank = ((ItemMatchers.Partial) matchResult).getRank();
selectedItem = Optional.of(itemToCompare);
}
}
returnselectedItem;
}
}