diff --git a/source/net/sourceforge/filebot/similarity/Matcher.java b/source/net/sourceforge/filebot/similarity/Matcher.java index 9c0ba2a5..ec59004b 100644 --- a/source/net/sourceforge/filebot/similarity/Matcher.java +++ b/source/net/sourceforge/filebot/similarity/Matcher.java @@ -2,10 +2,13 @@ package net.sourceforge.filebot.similarity; +import static java.util.Collections.*; + import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Iterator; @@ -28,7 +31,7 @@ public class Matcher { private final DisjointMatchCollection disjointMatchCollection; - + public Matcher(Collection values, Collection candidates, boolean strict, SimilarityMetric[] metrics) { this.values = new LinkedList(values); this.candidates = new LinkedList(candidates); @@ -39,7 +42,7 @@ public class Matcher { this.disjointMatchCollection = new DisjointMatchCollection(); } - + public synchronized List> match() throws InterruptedException { // list of all combinations of values and candidates List> possibleMatches = new ArrayList>(values.size() * candidates.size()); @@ -77,22 +80,31 @@ public class Matcher { return result; } - + public synchronized List remainingValues() { return Collections.unmodifiableList(values); } - + public synchronized List remainingCandidates() { return Collections.unmodifiableList(candidates); } - + protected void deepMatch(Collection> possibleMatches, int level) throws InterruptedException { if (level >= metrics.length || possibleMatches.isEmpty()) { // add the first possible match if non-strict, otherwise ignore ambiguous matches if (!strict) { - disjointMatchCollection.addAll(possibleMatches); + // order alphabetically to get more predictable matching (when no matching is possible anymore) + List> rest = new ArrayList>(possibleMatches); + sort(rest, new Comparator>() { + + @Override + public int compare(Match o1, Match o2) { + return o1.toString().compareToIgnoreCase(o2.toString()); + } + }); + disjointMatchCollection.addAll(rest); } // no further refinement possible @@ -119,7 +131,7 @@ public class Matcher { } } - + protected void removeCollected(Collection> matches) { for (Iterator> iterator = matches.iterator(); iterator.hasNext();) { if (!disjointMatchCollection.disjoint(iterator.next())) @@ -127,7 +139,7 @@ public class Matcher { } } - + protected SortedMap>> mapBySimilarity(Collection> possibleMatches, SimilarityMetric metric) throws InterruptedException { // map sorted by similarity descending SortedMap>> similarityMap = new TreeMap>>(Collections.reverseOrder()); @@ -154,7 +166,7 @@ public class Matcher { return similarityMap; } - + protected List> disjointMatches(Collection> collection) { Map>> matchesByValue = new HashMap>>(); Map>> matchesByCandidate = new HashMap>>(); @@ -195,7 +207,7 @@ public class Matcher { return disjointMatches; } - + protected static class DisjointMatchCollection extends AbstractList> { private final List> matches = new ArrayList>(); @@ -203,7 +215,7 @@ public class Matcher { private final Map> values = new IdentityHashMap>(); private final Map> candidates = new IdentityHashMap>(); - + @Override public boolean add(Match match) { if (disjoint(match)) { @@ -216,34 +228,34 @@ public class Matcher { return false; } - + public boolean disjoint(Match match) { return !values.containsKey(match.getValue()) && !candidates.containsKey(match.getCandidate()); } - + public Match getByValue(V value) { return values.get(value); } - + public Match getByCandidate(C candidate) { return candidates.get(candidate); } - + @Override public Match get(int index) { return matches.get(index); } - + @Override public int size() { return matches.size(); } - + @Override public void clear() { matches.clear();