按字母顺序对列表中的特定值排序(如果存在)

时间:2016-08-23 03:39:31

标签: java sorting java-8

我正在为满足以下测试用例的比较器寻找最易读的定义:

@Test
public void testComparator() {
    List<String> toSort = Lists.newArrayList("a", "b", "c", "d", "e", "f");
    Collections.shuffle(toSort);
    Comparator<String> theSolution = ???; 
    Collections.sort(toSort, theSolution);
    System.out.println(toSort); // Prints [c, a, b, d, e, f]
}

我已经尝试过使用Guava&#39; s Ordering定义的比较器:

Ordering.explicit("c").thenComparing(Ordering.natural());

但是,explicit会为未枚举的项引发异常。所以解决方案失败了。有什么建议吗?

4 个答案:

答案 0 :(得分:4)

您可以明确地编写比较函数,例如

Comparator<String> theSolution = Comparator.comparing(a -> a.equals("c") ? "" : a);
// treat "c" as the same as the empty string "" when sorting which will be ranked first.

答案 1 :(得分:3)

从您的示例中不清楚您是否希望不是“c”的成员保持当前顺序或按字母顺序排序。如果你想在前面排序“c”并留下余数,那么你可以使用:

Comparator.comparing("c"::equals).reversed();

需要反转比较器,因为布尔值的自然排序首先为假。

按字母顺序对剩余项目进行排序可以通过以下方式实现:

Comparator.comparing("c"::equals).reversed()
    .thenComparing(Object::toString, String::compareTo);

答案 2 :(得分:1)

由于您使用的是Guava,因此这是使用ComparisonChain的解决方案。我喜欢他们明确的布尔优先级:

Comparator<String> theSolution = (a, b) -> ComparisonChain.start()
        .compareTrueFirst(a.equals("c"), b.equals("c"))
        .compare(a, b)
        .result();

答案 3 :(得分:0)

好吧,您可以使用像

这样的比较器链来组合这些任务
XmlDocument doc = new XmlDocument();
doc.Load("persons.xml");

XmlNode currNode = doc.DocumentElement.FirstChild;
Console.WriteLine("First person...");
Console.WriteLine(currNode.OuterXml);

XmlNode nextNode = currNode.NextSibling;
Console.WriteLine("\r\nSecond person...");
Console.WriteLine(nextNode.OuterXml); 

但您也可以考虑将这两个任务分开,先排序,然后将所需的值移到前面:

List<String> toSort = Arrays.asList("a", "b", "c", "d", "e", "f");
Collections.shuffle(toSort);

toSort.sort(Comparator.comparing((String s) -> !s.equals("c"))
                      .thenComparing(Comparator.naturalOrder()));

System.out.println(toSort); // Prints [c, a, b, d, e, f]

这也适用于多次出现。