Created
November 9, 2017 16:49
-
-
Save rdblue/7e80e9700d508d395b004c4c146dbfe2 to your computer and use it in GitHub Desktop.
Java Comparators for CharSequence and ByteBuffer
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
import java.nio.ByteBuffer; | |
import java.util.Comparator; | |
public class Comparators { | |
public static Comparator<ByteBuffer> unsignedBytes() { | |
return UnsignedByteBufComparator.INSTANCE; | |
} | |
public static Comparator<ByteBuffer> signedBytes() { | |
return Comparator.naturalOrder(); | |
} | |
@SuppressWarnings("unchecked") | |
public static <T> Comparator<T> nullsFirst() { | |
return (Comparator<T>) NullsFirst.INSTANCE; | |
} | |
@SuppressWarnings("unchecked") | |
public static <T> Comparator<T> nullsLast() { | |
return (Comparator<T>) NullsLast.INSTANCE; | |
} | |
public static Comparator<CharSequence> charSequences() { | |
return CharSeqComparator.INSTANCE; | |
} | |
private static class NullsFirst<T> implements Comparator<T> { | |
private static final NullsFirst<?> INSTANCE = new NullsFirst<>(); | |
private NullsFirst() { | |
} | |
@Override | |
public int compare(T o1, T o2) { | |
if (o1 != null) { | |
if (o2 != null) { | |
return 0; | |
} | |
return 1; | |
} else if (o2 != null) { | |
return -1; | |
} | |
return 0; | |
} | |
@Override | |
public Comparator<T> thenComparing(Comparator<? super T> other) { | |
return new NullSafeChainedComparator<>(this, other); | |
} | |
} | |
private static class NullsLast<T> implements Comparator<T> { | |
private static final NullsLast<?> INSTANCE = new NullsLast<>(); | |
private NullsLast() { | |
} | |
@Override | |
public int compare(T o1, T o2) { | |
if (o1 != null) { | |
if (o2 != null) { | |
return 0; | |
} | |
return -1; | |
} else if (o2 != null) { | |
return 1; | |
} | |
return 0; | |
} | |
@Override | |
public Comparator<T> thenComparing(Comparator<? super T> other) { | |
return new NullSafeChainedComparator<>(this, other); | |
} | |
} | |
private static class NullSafeChainedComparator<T> implements Comparator<T> { | |
private final Comparator<T> first; | |
private final Comparator<? super T> second; | |
public NullSafeChainedComparator(Comparator<T> first, Comparator<? super T> second) { | |
this.first = first; | |
this.second = second; | |
} | |
@Override | |
public int compare(T o1, T o2) { | |
int cmp = first.compare(o1, o2); | |
if (cmp == 0 && o1 != null) { | |
return second.compare(o1, o2); | |
} | |
return cmp; | |
} | |
} | |
private static class UnsignedByteBufComparator implements Comparator<ByteBuffer> { | |
private static final UnsignedByteBufComparator INSTANCE = new UnsignedByteBufComparator(); | |
private UnsignedByteBufComparator() { | |
} | |
@Override | |
public int compare(ByteBuffer buf1, ByteBuffer buf2) { | |
int len = Math.min(buf1.remaining(), buf2.remaining()); | |
// find the first difference and return | |
int b1pos = buf1.position(); | |
int b2pos = buf2.position(); | |
for (int i = 0; i < len; i += 1) { | |
// Conversion to int is what Byte.toUnsignedInt would do | |
int cmp = Integer.compare( | |
((int) buf1.get(b1pos + i)) & 0xff, | |
((int) buf2.get(b2pos + i)) & 0xff); | |
if (cmp != 0) { | |
return cmp; | |
} | |
} | |
// if there are no differences, then the shorter seq is first | |
return Integer.compare(buf1.remaining(), buf2.remaining()); | |
} | |
} | |
private static class CharSeqComparator implements Comparator<CharSequence> { | |
private static final CharSeqComparator INSTANCE = new CharSeqComparator(); | |
private CharSeqComparator() { | |
} | |
@Override | |
public int compare(CharSequence s1, CharSequence s2) { | |
int len = Math.min(s1.length(), s2.length()); | |
// find the first difference and return | |
for (int i = 0; i < len; i += 1) { | |
int cmp = Character.compare(s1.charAt(i), s2.charAt(i)); | |
if (cmp != 0) { | |
return cmp; | |
} | |
} | |
// if there are no differences, then the shorter seq is first | |
return Integer.compare(s1.length(), s2.length()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment