Java – 对包含特殊字符的对象列表进行排序

huangapple go评论81阅读模式
英文:

Java - Sort a list of objects that includes a special character

问题

基本上,我有一个对象的ArrayList,如下所示:

[{name: 'A'}, {name: 'B'}, {name:'?'}]

我希望对它们进行排序,以使问号像上面一样排在末尾。

但使用以下代码:

Collections.sort(myList);

这总是导致带有问号的对象首先出现,我认为这是由于ASCII排序造成的?我认为正确的方法是使用比较器函数,但我不确定在字母和特殊字符方面该如何实现?

我应该如何实现这个?

英文:

Basically i have an arraylist of objects like so:

[{name: 'A'}, {name: 'B'}, {name:'?'}]

I want to sort these so that the question mark is at the end like above.

But using the below code.

Collections.sort(myList);

This always results in the object with the question mark first, I think this is due to ASCII ordering? I think the correct way forward is to use a comparator function but i'm not sure how that would take shape with letters and special characters?

How would I implement this?

答案1

得分: 2

一种替代方法是,可以使用基于规则的排序器将任何标点符号排序到末尾。

一个示例:

List<String> words = Arrays.asList(
        "?dog", "rat", "456", "123", "dog", "pig", "?cat", "!rat", "cat"
);
String englishRules = ("< a,A < b,B < c,C < d,D < e,E < f,F "
        + "< g,G < h,H < i,I < j,J < k,K < l,L "
        + "< m,M < n,N < o,O < p,P < q,Q < r,R "
        + "< s,S < t,T < u,U < v,V < w,W < x,X "
        + "< y,Y < z,Z < 0,1,2,3,4,5,6,7,8,9");

RuleBasedCollator rbc = new RuleBasedCollator(englishRules);
rbc.setStrength(Collator.PRIMARY);

Collections.sort(words, rbc);
words.forEach((word) -> {
    out.print(word + " ");
});

这将输出:

cat dog pig rat 123 456 !rat ?cat ?dog 

需要注意的点:

  1. 这个特定的示例仅限于英文排序。

  2. 这种通用技术之所以有效,是因为所有未提及的字符都被排序到末尾。因此,不仅标点符号在英文字母和数字之后排序,其他字符/符号(例如其他脚本使用的字符)也是如此。

  3. 如果你想要非Unicode标点符号的排序顺序,它们需要在规则字符串中用单引号括起来:

"... < 0,1,2,3,4,5,6,7,8,9 < '?' < '!'"
英文:

An alternative approach - one which sorts any punctuation to the end - can be achieved using a rules-based collator.

An example:

List&lt;String&gt; words = Arrays.asList(
        &quot;?dog&quot;, &quot;rat&quot;, &quot;456&quot;, &quot;123&quot;, &quot;dog&quot;, &quot;pig&quot;, &quot;?cat&quot;, &quot;!rat&quot;, &quot;cat&quot;
);
String englishRules = (&quot;&lt; a,A &lt; b,B &lt; c,C &lt; d,D &lt; e,E &lt; f,F &quot;
        + &quot;&lt; g,G &lt; h,H &lt; i,I &lt; j,J &lt; k,K &lt; l,L &quot;
        + &quot;&lt; m,M &lt; n,N &lt; o,O &lt; p,P &lt; q,Q &lt; r,R &quot;
        + &quot;&lt; s,S &lt; t,T &lt; u,U &lt; v,V &lt; w,W &lt; x,X &quot;
        + &quot;&lt; y,Y &lt; z,Z &lt; 0,1,2,3,4,5,6,7,8,9&quot;);

RuleBasedCollator rbc = new RuleBasedCollator(englishRules);
rbc.setStrength(Collator.PRIMARY);

Collections.sort(words, rbc);
words.forEach((word) -&gt; {
    out.print(word + &quot; &quot;);
});

This outputs:

cat dog pig rat 123 456 !rat ?cat ?dog 

Points to note:

  1. This specific example is limited to an English collation.

  2. The general technique works because all non-mentioned characters are sorted to the end. So, not only are punctuation symbols sorted after English letters and digits - but so is every other character/symbol (e.g. those used by other scripts).

  3. If you want a non-Unicode ordering of punctuation symbols, they need to be surrounded by single quotes in your rule string:

&quot;... &lt; 0,1,2,3,4,5,6,7,8,9 &lt; &#39;?&#39; &lt; &#39;!&#39;&quot;

答案2

得分: 1

在Java 8中,你可以使用两级自定义比较器:

// 给定
List<YourObject> list;
list.sort((o1, o2) -> "?".equals(o1.getName()) ? 1 :
    ("?".equals(o2.getName()) ? -1 : o1.getName().compareTo(o2.getName())));

这里的排序逻辑是,如果其中一个或另一个名称为 ?,那么我们始终将该 ? 排在最后。如果两个名称都是 ?,或者两个名称都不是 ?,那么我们使用默认的字典序字符串排序。

英文:

In Java 8, you may use a two-tiered custom comparator:

// given
List&lt;YourObject&gt; list;
list.sort((o1, o2) -&gt; &quot;?&quot;.equals(o1.getName()) ? 1 :
    (&quot;?&quot;.equals(o2.getName()) ? -1 : o1.getName().compareTo(o2.getName())));

The sorting logic here is that if one or the other names be ?, then we always sort that ? last. If both names be ?, or if neither be ?, then we sort using the default lexicographical string sorting.

答案3

得分: 1

以下是您要求的代码的中文翻译部分:

您可以使用`java.util.Comparator`中的一些有用方法,使您的生活变得更加轻松,您的代码也不再容易出错,而不需要考虑if-else或三元运算符:

    class MyObj {
        private String name;
    
        MyObj(String name) {
            this.name = name;
        }
    
        String getName() {
            return name;
        }
    
        @Override
        public String toString() {
            return "name: '" + name + "'";
        }
    }
    
    public class Demo {
        public static void main(String[] args) {
            List<MyObj> lst = Arrays.asList(new MyObj("B"), new MyObj("?"), new MyObj("A"));
            Comparator<String> questionMarksLast = Comparator
                    .<String, Boolean>comparing("?".equals)
                    .thenComparing(Comparator.naturalOrder());
    
            lst.sort(Comparator.comparing(MyObj::getName, questionMarksLast));
            System.out.println(lst);  // 输出 [{name: 'A'}, {name: 'B'}, {name: '?'}]
        }
    }
英文:

You can use some useful methods from java.util.Comparator to make your life easier and your code less error-prone than having to think about if-else or ternary operators:

class MyObj {
    private String name;

    MyObj(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }

    @Override
    public String toString() {
        return &quot;{name: &#39;&quot; + name + &quot;&#39;}&quot;;
    }
}

public class Demo {
    public static void main(String[] args) {
        List&lt;MyObj&gt; lst = Arrays.asList(new MyObj(&quot;B&quot;), new MyObj(&quot;?&quot;), new MyObj(&quot;A&quot;));
        Comparator&lt;String&gt; questionMarksLast = Comparator
                .&lt;String, Boolean&gt;comparing(&quot;?&quot;::equals)
                .thenComparing(Comparator.naturalOrder());

        lst.sort(Comparator.comparing(MyObj::getName, questionMarksLast));
        System.out.println(lst);  // prints [{name: &#39;A&#39;}, {name: &#39;B&#39;}, {name: &#39;?&#39;}]
    }
}

huangapple
  • 本文由 发表于 2020年4月3日 23:57:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/61015766.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定