我现在有一个代码片段,它以升序返回列表中的字符串:
Collections.sort(myList, new Comparator<MyClass>() {
@Override
public int compare(MyClass o1, MyClass o2) {
return o1.aString.compareTo(o2.aString);
}
});
当它工作的时候,我想添加一些自定义的“规则”到顺序中,把某些字符串放在前面。
if(aString.equals("Hi")){
// put string first in the order
}
if(aString begins with a null character, e.g. " ") {
// put string after Hi, but before the other strings
}
// So the order could be: Hi, _string, a_string, b_string, c_string
是否可以像这样使用Comparator
自定义列表的排序?
3条答案
按热度按时间ubby3x7f1#
MC Emperor的answer非常好(+1),因为它满足了OP不使用Java 8 API的要求。它还使用了一种简洁的内部函数技术(
getOrder
方法),将条件Map到小整数值,以实现第一级比较。这里有一个使用Java8构造的替代方法,它假设
MyClass
有一个getString
方法,该方法执行显而易见的操作。在您习惯这种风格之前,这是非常不透明的,关键的一点是,提供给
Comparator.comparing
和Comparator.thenComparing
的“extractor”函数通常只是提取一个字段,但是它可以是到任何其他值的一般Map。如果那个值是Comparable,那么就不需要为它提供额外的Comparator。在这种情况下,提取器函数是一个布尔表达式。这被装箱为一个布尔值,结果是Comparable。由于false
的顺序在true
之前,我们需要对布尔表达式求反。还要注意,我必须为lambda参数提供一个显式的类型声明,因为类型推断通常不适用于像这样的链式比较器情况。
y1aodyip2#
有可能。
使用Java 8功能
你可以传递一个函数给
Comparator.comparing
方法来定义你的规则,注意我们只返回整数,最小的整数代表应该先出现的元素。如果你想让剩下的元素按字母顺序排序,你可以使用
thenComparing(Comparator.naturalOrder())
,如果你的类实现了Comparable
,否则,你应该先提取排序键:注意,返回的具体数字并不重要,重要的是排序时较小的数字在较大的数字之前,所以如果总是把字符串"Hi"放在第一位,那么对应的数字应该是返回的最小数字(在我的例子中是0)。
使用Java〈= 7项功能(兼容Android API级别21)
如果Java 8功能对您不可用,那么您可以这样实现它:
就像这样称呼它:
其工作原理如下:首先,将收到的两个字符串Map到您的自定义规则集,然后相减。如果两者不同,则运算
Integer.compare(getOrder(o1), getOrder(o2))
1确定比较。否则,如果两者相同,则使用词法顺序进行比较。Here is some code in action.
1始终使用
Integer::compare
,而不是用一个减去另一个,因为整数溢出可能导致错误结果。See here。ndasle7k3#
是的,这是可能的,您可以完全控制compareTo()方法。
1.使用String#equals而不是==来比较字符串
1.确保检查compareTo的两个参数是否存在异常情况。
一种实现某事的具体方法,其中一些词总是在前,一些词总是在后,但在例外情况下定义了顺序: