added LexicographicIterableComparator

This commit is contained in:
2021-01-03 22:15:18 +01:00
parent 2cdc92effb
commit 046250caaa
3 changed files with 99 additions and 1 deletions

View File

@@ -1 +1 @@
sbt.version=1.4.1
sbt.version=1.4.3

View File

@@ -0,0 +1,30 @@
package net.woggioni.jwo.collection;
import java.util.Comparator;
import java.util.Iterator;
public class LexicographicIterableComparator<T> implements Comparator<Iterable<T>> {
private final Comparator<T> elementComparator;
public LexicographicIterableComparator(final Comparator<T> elementComparator) {
this.elementComparator = elementComparator;
}
@Override
public int compare(Iterable<T> iterable1, Iterable<T> iterable2) {
final Iterator<T> 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 <S extends Comparable<S>> LexicographicIterableComparator<S> forClass(Class<S> cls) {
return new LexicographicIterableComparator<S>(Comparator.naturalOrder());
}
}

View File

@@ -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<Integer> DESCENDING_INTEGER_COMPARATOR = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return -o1.compareTo(o2);
}
};
@Test
public void equal() {
final List<Integer> l1 = Arrays.asList(1, 2, 3);
final List<Integer> l2 = Arrays.asList(1, 2, 3);
final LexicographicIterableComparator<Integer> c = LexicographicIterableComparator.forClass(Integer.class);
assertEquals(0,c.compare(l1, l2));
}
@Test
public void sameLengthAscending() {
final List<Integer> l1 = Arrays.asList(1, 2, 3);
final List<Integer> l2 = Arrays.asList(1, 2, 4);
final LexicographicIterableComparator<Integer> c = LexicographicIterableComparator.forClass(Integer.class);
assertEquals(-1,c.compare(l1, l2));
}
@Test
public void sameLengthDescending() {
final List<Integer> l1 = Arrays.asList(1, 2, 3);
final List<Integer> l2 = Arrays.asList(1, 2, 4);
final LexicographicIterableComparator<Integer> c = new LexicographicIterableComparator<>(DESCENDING_INTEGER_COMPARATOR);
assertEquals(1,c.compare(l1, l2));
}
@Test
public void differentLengthAscending() {
final List<Integer> l1 = Arrays.asList(1, 2, 3);
final List<Integer> l2 = Arrays.asList(1, 2);
final LexicographicIterableComparator<Integer> c = LexicographicIterableComparator.forClass(Integer.class);
assertEquals(1,c.compare(l1, l2));
}
@Test
public void differentLengthAndValuesDescending() {
final List<Integer> l1 = Arrays.asList(1, 3, 3); // we need different values, the shorter will always come first otherwise
final List<Integer> l2 = Arrays.asList(1, 2);
final LexicographicIterableComparator<Integer> c = new LexicographicIterableComparator<>(DESCENDING_INTEGER_COMPARATOR);
assertEquals(-1,c.compare(l1, l2));
}
@Test
public void differentLengthDescending() {
final List<Integer> l1 = Arrays.asList(1, 2, 3);
final List<Integer> l2 = Arrays.asList(1, 2);
final LexicographicIterableComparator<Integer> c = new LexicographicIterableComparator<>(DESCENDING_INTEGER_COMPARATOR);
assertEquals(1,c.compare(l1, l2)); // this is counterintuitive: the shortest comes first event in this case!
}
}