【问题标题】:Sorting of ArrayList using Comparator in Java在 Java 中使用 Comparator 对 ArrayList 进行排序
【发布时间】:2017-11-17 14:21:55
【问题描述】:

我在使用升序对 ArrayList 进行排序时遇到问题。我正在使用 Comparator 和 Collat​​or Of Collection 类。如何实现预期的排序顺序?非常感谢您的帮助。

算法计算的升序为:

[AutomationRejectNotification|,AutomationRejectNotification1011, AutomationRejectNotification1021,AutomationTestNotification1, AutomationTestNotification100,AutomationTestNotification2,testDisplay Template, Testing Chrome, Testing Field, Test Notfication, testnotif, Test Notification #1]

预期升序排序为:

[AutomationRejectNotification1011, AutomationRejectNotification1021, AutomationRejectNotification|,AutomationTestNotification1, AutomationTestNotification2,AutomationTestNotification100,Test Notfication, Test Notification #1, testDisplay Template, Testing Chrome, Testing Field, testnotif]

Java 代码:

public static void listSort(List<String> o1, boolean order) {
        final Pattern p = Pattern.compile("^\\d+");
        Comparator<String> c = new Comparator<String>() {
            public int compare(String object1, String object2) {
                Collator collator = Collator.getInstance(Locale.US);
                Matcher m = p.matcher(object1);

                if (!m.find()) {
                    return collator.compare(object1, object2);
                } else {
                    Long number2 = null;
                    Long number1 = Long.parseLong(m.group());

                    m = p.matcher(object2);
                    if (!m.find()) {
                        return collator.compare(object1, object2);
                    } else {

                        number2 = Long.parseLong(m.group());

                        int comparison = number1.compareTo(number2);
                        if (comparison != 0) {
                            return comparison;
                        } else {
                            return collator.compare(object1, object2);
                        }
                    }
                }


            }
        };
        o1.sort(c);

【问题讨论】:

  • 这就是 Collat​​or 的工作方式。看看这篇文章:documentation.progress.com/output/Corticon/5.3.2/…
  • 不,@WinterN,Collator 的工作方式不是。请特别注意,在美国语言环境中,| 字符出现在十进制数字之后,因此"AutomationRejectNotification|""AutomationRejectNotification1011" 之后排序,这与 OP 报告的顺序相反。
  • @kaps - 您能否指定适用于任意输入列表的排序规则,而不是提供预期输出的单个示例?

标签: java sorting collections comparator collator


【解决方案1】:

你的Comparator 没有正确实现Comparator 接口的合约,所以所有的赌注都没有了。 compare() 方法必须具有所有这些属性:

sgn(compare(x, y)) == -sgn(compare(y, x)) 表示所有 x 和 y。

((compare(x, y)&gt;0) &amp;&amp; (compare(y, z)&gt;0)) 隐含compare(x, z)&gt;0

compare(x, y)==0 表示 sgn(compare(x, z))==sgn(compare(y, z)) 用于所有 z。

(API docs)

当被比较的两个字符串都包含一个非空的十进制数字序列时,您通过数字进行比较,而如果至少一个字符串没有任何数字,则您通过整理器进行比较。这会产生以下结果:

compare("z1", "y") > 0

compare("y", "x3") > 0

compare("z1", "x3") < 0

,不符合第二个要求的属性(传递性)。

您可能想要做的是将最长的前导无数字子串作为第一个标准进行比较,通过比较尾随数字(如果有)来打破任何联系。可能看起来像这样:

public static void listSort(List<String> o1, boolean order) {
    final Pattern p = Pattern.compile("([^0-9]*)([0-9]+)?");
    final Collator collator = Collator.getInstance(Locale.US);
    Comparator<String> c = new Comparator<String>() {
        public int compare(String object1, String object2) {
            Matcher m1 = p.matcher(object1);
            Matcher m2 = p.matcher(object2);

            if (!m1.lookingAt() || !m2.lookingAt()) {
                assert false : "Should never happen";
            }

            int result = collator.compare(m1.group(1), m2.group(1));

            if (result == 0) {
                String digits1 = m1.group(2);
                String digits2 = m2.group(2);

                if (digits1 != null && digits2 != null) {
                    Long number1 = Long.valueOf(digits1);
                    Long number2 = Long.valueOf(digits2);
                    result = number1.compareTo(number2);
                } else if (digits1 != null) {
                    result = 1;
                } else if (digits2 != null) {
                    result = -1;
                }
            }

            return result;
        }
    };
    o1.sort(c);
}

这将与您提供的预期顺序一致,但还有其他排序方案也会为这些特定元素产生相同的结果。

【讨论】:

  • 嗨@John Bollinger:感谢您的意见。它抛出错误 .java.lang.NumberFormatException: For input string: "Test-AutomationTestNotification" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Long.parseLong(Long.java:589)在 java.lang.Long.valueOf(Long.java:803)
  • 我在一些测试数据中有所有特殊字符。即测试 Motification #1,Test Motifcaiotn@34
  • @kaps,我怀疑你可以自己解决这个问题,但我已经解决了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-19
相关资源
最近更新 更多