diff --git a/project/build.properties b/project/build.properties index 08e4d79..947bdd3 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.4.1 +sbt.version=1.4.3 diff --git a/src/main/java/net/woggioni/jwo/collection/LexicographicIterableComparator.java b/src/main/java/net/woggioni/jwo/collection/LexicographicIterableComparator.java new file mode 100644 index 0000000..9a474ab --- /dev/null +++ b/src/main/java/net/woggioni/jwo/collection/LexicographicIterableComparator.java @@ -0,0 +1,30 @@ +package net.woggioni.jwo.collection; + + +import java.util.Comparator; +import java.util.Iterator; + +public class LexicographicIterableComparator implements Comparator> { + + private final Comparator elementComparator; + + public LexicographicIterableComparator(final Comparator elementComparator) { + this.elementComparator = elementComparator; + } + + @Override + public int compare(Iterable iterable1, Iterable iterable2) { + final Iterator it1 = iterable1.iterator(), it2 = iterable2.iterator(); + while (it1.hasNext() && it2.hasNext()) { + final int cmp = elementComparator.compare(it1.next(),it2.next()); + if (cmp != 0) return cmp; + } + if (it1.hasNext()) return 1; + if (it2.hasNext()) return -1; + return 0; + } + + public static > LexicographicIterableComparator forClass(Class cls) { + return new LexicographicIterableComparator(Comparator.naturalOrder()); + } +} \ No newline at end of file diff --git a/src/test/java/net/woggioni/jwo/collection/LexicographicIterableComparatorTest.java b/src/test/java/net/woggioni/jwo/collection/LexicographicIterableComparatorTest.java new file mode 100644 index 0000000..d425682 --- /dev/null +++ b/src/test/java/net/woggioni/jwo/collection/LexicographicIterableComparatorTest.java @@ -0,0 +1,68 @@ +package net.woggioni.jwo.collection; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + + +public class LexicographicIterableComparatorTest { + + private final static Comparator DESCENDING_INTEGER_COMPARATOR = new Comparator() { + public int compare(Integer o1, Integer o2) { + return -o1.compareTo(o2); + } + }; + + @Test + public void equal() { + final List l1 = Arrays.asList(1, 2, 3); + final List l2 = Arrays.asList(1, 2, 3); + final LexicographicIterableComparator c = LexicographicIterableComparator.forClass(Integer.class); + assertEquals(0,c.compare(l1, l2)); + } + + @Test + public void sameLengthAscending() { + final List l1 = Arrays.asList(1, 2, 3); + final List l2 = Arrays.asList(1, 2, 4); + final LexicographicIterableComparator c = LexicographicIterableComparator.forClass(Integer.class); + assertEquals(-1,c.compare(l1, l2)); + } + + @Test + public void sameLengthDescending() { + final List l1 = Arrays.asList(1, 2, 3); + final List l2 = Arrays.asList(1, 2, 4); + final LexicographicIterableComparator c = new LexicographicIterableComparator<>(DESCENDING_INTEGER_COMPARATOR); + assertEquals(1,c.compare(l1, l2)); + } + + @Test + public void differentLengthAscending() { + final List l1 = Arrays.asList(1, 2, 3); + final List l2 = Arrays.asList(1, 2); + final LexicographicIterableComparator c = LexicographicIterableComparator.forClass(Integer.class); + assertEquals(1,c.compare(l1, l2)); + } + + @Test + public void differentLengthAndValuesDescending() { + final List l1 = Arrays.asList(1, 3, 3); // we need different values, the shorter will always come first otherwise + final List l2 = Arrays.asList(1, 2); + final LexicographicIterableComparator c = new LexicographicIterableComparator<>(DESCENDING_INTEGER_COMPARATOR); + assertEquals(-1,c.compare(l1, l2)); + } + + @Test + public void differentLengthDescending() { + final List l1 = Arrays.asList(1, 2, 3); + final List l2 = Arrays.asList(1, 2); + final LexicographicIterableComparator c = new LexicographicIterableComparator<>(DESCENDING_INTEGER_COMPARATOR); + assertEquals(1,c.compare(l1, l2)); // this is counterintuitive: the shortest comes first event in this case! + } +}