Car*_*ter 8 java design-patterns comparator
我正在编写一些自定义比较器,我希望它们将空项目推送到列表的底部,无论我是按升序还是降序排序.接近这个的好策略或模式是什么?
随口说说:
还有其他策略吗?我想听听有关不同方法的任何经验,以及各种策略的任何陷阱.
dfa*_*dfa 11
我同意Jon Skeet(这很容易:).我试图实现一个非常简单的装饰器:
class NullComparators {
static <T> Comparator<T> atEnd(final Comparator<T> comparator) {
return new Comparator<T>() {
public int compare(T o1, T o2) {
if (o1 == null && o2 == null) {
return 0;
}
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
return comparator.compare(o1, o2);
}
};
}
static <T> Comparator<T> atBeginning(final Comparator<T> comparator) {
return Collections.reverseOrder(atEnd(comparator));
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于比较者:
Comparator<String> wrapMe = new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
Run Code Online (Sandbox Code Playgroud)
和一些测试数据:
List<String> strings = Arrays.asList(null, "aaa", null, "bbb", "ccc", null);
Run Code Online (Sandbox Code Playgroud)
您可以在结尾处使用空值排序:
Collections.sort(strings, NullComparators.atEnd(wrapMe));
Run Code Online (Sandbox Code Playgroud)
[aaa, bbb, ccc, null, null, null]
或者在开始时:
Collections.sort(strings, NullComparators.atBeginning(wrapMe));
Run Code Online (Sandbox Code Playgroud)
[null, null, null, ccc, bbb, aaa]
最后一个选项对我很有吸引力.比较器非常适合链接在一起.特别是你可能想要写一个ReverseComparator以及一个NullWrappingComparator.
编辑:你不必自己写.如果您查看Google Collections Library中的Ordering类,您会发现这个以及各种其他好东西:)
编辑:进入更多细节,以显示我的意思ReverseComparator...
一个警告 - 在执行a时ReverseComparator,反转参数的顺序而不是否定结果,否则Integer.MIN_VALUE将"逆转"到自身.
所以这个实现是错误的(假设original是比较器反转):
public int compare(T x, T y)
{
return -original.compare(x, y);
}
Run Code Online (Sandbox Code Playgroud)
但这是对的:
public int compare(T x, T y)
{
return original.compare(y, x);
}
Run Code Online (Sandbox Code Playgroud)
原因是我们总是想要反转比较,但如果original.compare(x, y)返回int.MIN_VALUE,那么坏的比较器也将返回int.MIN_VALUE,这是不正确的.这是由于有趣的财产int.MIN_VALUE == -int.MIN_VALUE.
继续讨论dfa的答案 - 我想要的是空值在最后排序而不影响非空值的顺序.所以我想要更多的东西:
public class NullComparatorsTest extends TestCase {
Comparator<String> forward = new Comparator<String>() {
public int compare(String a, String b) {
return a.compareTo(b);
}
};
public void testIt() throws Exception {
List<String> strings = Arrays.asList(null, "aaa", null, "bbb", "ccc", null);
Collections.sort(strings, NullComparators.atEnd(forward));
assertEquals("[aaa, bbb, ccc, null, null, null]", strings.toString());
Collections.sort(strings, NullComparators.atBeginning(forward));
assertEquals("[null, null, null, aaa, bbb, ccc]", strings.toString());
}
}
public class NullComparators {
public static <T> Comparator<T> atEnd(final Comparator<T> comparator) {
return new Comparator<T>() {
public int compare(T a, T b) {
if (a == null && b == null)
return 0;
if (a == null)
return 1;
if (b == null)
return -1;
return comparator.compare(a, b);
}
};
}
public static <T> Comparator<T> atBeginning(final Comparator<T> comparator) {
return new Comparator<T>() {
public int compare(T a, T b) {
if (a == null && b == null)
return 0;
if (a == null)
return -1;
if (b == null)
return 1;
return comparator.compare(a, b);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,这完全归功于dfa - 这只是对他作品的一个小修改.
在 Java 8 中,您可以使用 theComparator.nullsLast和Comparator.nullsFirststatic 方法来拥有更多对 null 友好的比较器。假设您有一个Fruit如下所示的类:
public class Fruit {
private final String name;
private final Integer size;
// Constructor and Getters
}
Run Code Online (Sandbox Code Playgroud)
如果您想按大小对一堆水果进行排序并将nulls 放在末尾:
List<Fruit> fruits = asList(null, new Fruit("Orange", 25), new Fruit("Kiwi", 5));
Run Code Online (Sandbox Code Playgroud)
你可以简单地写:
Collections.sort(fruits, Comparator.nullsLast(Comparator.comparingInt(Fruit::getSize)));
Run Code Online (Sandbox Code Playgroud)
结果将是:
[Fruit{name='Kiwi', size=5}, Fruit{name='Orange', size=25}, null]
Run Code Online (Sandbox Code Playgroud)