/* * This is free and unencumbered software released into the public domain. * * Anyone is free to copy, modify, publish, use, compile, sell, or * distribute this software, either in source code form or as a compiled * binary, for any purpose, commercial or non-commercial, and by any * means. * * In jurisdictions that recognize copyright laws, the author or authors * of this software dedicate any and all copyright interest in the * software to the public domain. We make this dedication for the benefit * of the public at large and to the detriment of our heirs and * successors. We intend this dedication to be an overt act of * relinquishment in perpetuity of all present and future rights to this * software under copyright law. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * For more information, please refer to <http://unlicense.org/> */ package jxtn.core.axi.comparators; import java.util.Comparator; import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.ToDoubleFunction; import java.util.function.ToIntFunction; import java.util.function.ToLongFunction; /** * 成員比較器。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @author AqD */ public final class MemberComparators { /** * 依照{@link Comparable}成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param <M> 代表{@code E}做比較的物件成員型態 * @param getMember 取得要代表{@code E}做比較的物件成員 * @return 依照{@code M}成員比較{@code E}的比較器 */ public static <E, M extends Comparable<?>> Comparator<E> byComparable(Function<E, M> getMember) { return new MemberComparableComparator<>(getMember); } /** * 依照boolean陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的boolean陣列成員 * @return 依照boolean陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfBoolean(Function<E, boolean[]> getMember) { return new AbstractMemberComparator<E, boolean[]>(getMember) { @Override protected int compareMember(boolean[] m1, boolean[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照byte陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的byte陣列成員 * @return 依照byte陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfByte(Function<E, byte[]> getMember) { return new AbstractMemberComparator<E, byte[]>(getMember) { @Override protected int compareMember(byte[] m1, byte[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照char陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的char陣列成員 * @return 依照char陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfChar(Function<E, char[]> getMember) { return new AbstractMemberComparator<E, char[]>(getMember) { @Override protected int compareMember(char[] m1, char[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照short陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的short陣列成員 * @return 依照short陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfShort(Function<E, short[]> getMember) { return new AbstractMemberComparator<E, short[]>(getMember) { @Override protected int compareMember(short[] m1, short[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照int陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的int陣列成員 * @return 依照int陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfInt(Function<E, int[]> getMember) { return new AbstractMemberComparator<E, int[]>(getMember) { @Override protected int compareMember(int[] m1, int[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照long陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的long陣列成員 * @return 依照long陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfLong(Function<E, long[]> getMember) { return new AbstractMemberComparator<E, long[]>(getMember) { @Override protected int compareMember(long[] m1, long[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照float陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的float陣列成員 * @return 依照float陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfFloat(Function<E, float[]> getMember) { return new AbstractMemberComparator<E, float[]>(getMember) { @Override protected int compareMember(float[] m1, float[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照double陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的double陣列成員 * @return 依照double陣列成員比較{@code E}的比較器 */ public static <E> Comparator<E> byArrayOfDouble(Function<E, double[]> getMember) { return new AbstractMemberComparator<E, double[]>(getMember) { @Override protected int compareMember(double[] m1, double[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照double陣列成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param <M> 代表{@code E}做比較的物件成員的陣列項目型態 * @param getMember 取得要代表{@code E}做比較的double陣列成員 * @return 依照double陣列成員比較{@code E}的比較器 */ @SuppressWarnings("rawtypes") public static <E, M extends Comparable> Comparator<E> byArrayOfComparable(Function<E, M[]> getMember) { return new AbstractMemberComparator<E, M[]>(getMember) { @Override protected int compareMember(M[] m1, M[] m2) { return ArrayComparators.compare(m1, m2); } }; } /** * 依照boolean成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的物件成員 * @return 依照boolean成員比較{@code E}的比較器 */ public static <E> Comparator<E> byBoolean(Predicate<E> getMember) { return new MemberBooleanComparator<>(getMember); } /** * 依照double成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的物件成員 * @return 依照double成員比較{@code E}的比較器 */ public static <E> Comparator<E> byDouble(ToDoubleFunction<E> getMember) { return new MemberDoubleComparator<>(getMember); } /** * 依照int成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的物件成員 * @return 依照int成員比較{@code E}的比較器 */ public static <E> Comparator<E> byInt(ToIntFunction<E> getMember) { return new MemberIntComparator<>(getMember); } /** * 依照long成員做比較。 * <p> * 支援null:null項目或成員作為較小的一方。 * </p> * * @param <E> 要比較的物件型態 * @param getMember 取得要代表{@code E}做比較的物件成員 * @return 依照long成員比較{@code E}的比較器 */ public static <E> Comparator<E> byLong(ToLongFunction<E> getMember) { return new MemberLongComparator<>(getMember); } private MemberComparators() { } private static abstract class AbstractMemberComparator<E, M> implements Comparator<E> { private final Function<E, M> getMember; public AbstractMemberComparator(Function<E, M> getMember) { this.getMember = getMember; } @Override public int compare(E o1, E o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } M m1 = this.getMember.apply(o1); M m2 = this.getMember.apply(o2); if (m1 == null && m2 == null) { return 0; } if (m1 == null) { return -1; } if (m2 == null) { return 1; } return this.compareMember(m1, m2); } protected abstract int compareMember(M m1, M m2); } private static class MemberComparableComparator<E, M extends Comparable<?>> implements Comparator<E> { public final Function<E, M> getMember; public MemberComparableComparator(Function<E, M> getMember) { Objects.requireNonNull(getMember); this.getMember = getMember; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public int compare(E o1, E o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } M m1 = this.getMember.apply(o1); M m2 = this.getMember.apply(o2); if (m1 == null && m2 == null) { return 0; } if (m1 == null) { return -1; } if (m2 == null) { return 1; } Comparable c1 = m1; return c1.compareTo(m2); } } private static class MemberBooleanComparator<E> implements Comparator<E> { public final Predicate<E> getMember; public MemberBooleanComparator(Predicate<E> getMember) { Objects.requireNonNull(getMember); this.getMember = getMember; } @Override public int compare(E o1, E o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } boolean m1 = this.getMember.test(o1); boolean m2 = this.getMember.test(o2); if (m1 && m2) { return 0; } if (m1) { return 1; } else { return -1; } } } private static class MemberDoubleComparator<E> implements Comparator<E> { public final ToDoubleFunction<E> getMember; public MemberDoubleComparator(ToDoubleFunction<E> getMember) { Objects.requireNonNull(getMember); this.getMember = getMember; } @Override public int compare(E o1, E o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } double m1 = this.getMember.applyAsDouble(o1); double m2 = this.getMember.applyAsDouble(o2); if (m1 == m2) { return 0; } if (m1 > m2) { return 1; } else { return -1; } } } private static class MemberIntComparator<E> implements Comparator<E> { public final ToIntFunction<E> getMember; public MemberIntComparator(ToIntFunction<E> getMember) { Objects.requireNonNull(getMember); this.getMember = getMember; } @Override public int compare(E o1, E o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } int m1 = this.getMember.applyAsInt(o1); int m2 = this.getMember.applyAsInt(o2); if (m1 == m2) { return 0; } if (m1 > m2) { return 1; } else { return -1; } } } private static class MemberLongComparator<E> implements Comparator<E> { public final ToLongFunction<E> getMember; public MemberLongComparator(ToLongFunction<E> getMember) { Objects.requireNonNull(getMember); this.getMember = getMember; } @Override public int compare(E o1, E o2) { if (o1 == null && o2 == null) { return 0; } if (o1 == null) { return -1; } if (o2 == null) { return 1; } long m1 = this.getMember.applyAsLong(o1); long m2 = this.getMember.applyAsLong(o2); if (m1 == m2) { return 0; } if (m1 > m2) { return 1; } else { return -1; } } } }