簡體   English   中英

我怎樣才能按照我想要的方式對這個ArrayList進行排序?

[英]How can I sort this ArrayList the way that I want?

這是一個ArrayList的簡單排序程序:

ArrayList<String> list = new ArrayList<String>();

list.add("1_Update");
list.add("11_Add");
list.add("12_Delete");
list.add("2_Create");

Collections.sort(list);
for (String str : list) {
  System.out.println(str.toString());
}

我期待這個程序的輸出為:

1_Update
2_Create
11_Add
12_Delete

但是當我運行這個程序時,我得到輸出為:

11_Add
12_Delete
1_Update
2_Create

為什么這樣,如何讓ArrayList按預期輸出顯示排序?

你可以編寫一個自定義比較器:

Collections.sort(list, new Comparator<String>() {
    public int compare(String a, String b) {
        return Integer.signum(fixString(a) - fixString(b));
    }
    private int fixString(String in) {
        return Integer.parseInt(in.substring(0, in.indexOf('_')));
    }
});

當您將此類數據排序為字符串時,它會比較字符本身,包括數字。 例如,所有以“1”開頭的字符串將一起結束。 所以訂單最終與此類似......

1 10 100 2 20 200

在任何時候,排序都“實現”您正在為字符串的子集分配含義,例如字符串前面的可變長度數字。 將數字排序為字符串時,用盡可能多的零填充左邊覆蓋最大數字可能會有所幫助,但是當您不控制數據時,它並沒有真正解決問題,如您的示例所示。 在那種情況下,排序將是......

001 002 010 020 100 200

它按文本(按字母順序)排序,而不是數字。 為了解決這個問題,您可以按照nsayer的回答中的建議實現自定義比較器。

它正在進行詞典比較。 它比較每個字符串中的第一個字符排序。 然后它將第二個字符串與相同的第一個字符進行比較。 當它將'_'字符與數字進行比較時,它的值大於任何單個數字字符,就像8> 7和a> 9.記住它正在進行字符比較而不是數字比較。

有一些方法可以實現自己的自定義排序路由,這可能比重命名腳本名稱更好。

如果重命名腳本名稱是一個選項,這可能允許使用其他腳本工具。 一種格式可能是

01_create_table.sql
02_create_index.sql
11_assign_privileges.sql

通過將前兩位數保持為兩個字符,詞典比較將起作用。

Collections.sort()方法的文檔說:

根據元素的自然順序,將指定列表按升序排序。

這意味着對於字符串,您將按字母順序獲取列表。 字符串11_assign_privileges.sql位於字符串1_create_table.sql之前,12_07_insert_static_data.sql位於1_create_table.sql之前。因此程序正在按預期工作。

您可以添加IComparable接口,然后按特定屬性進行排序。 例如,如果你有一個商店的商品集合,你可能想要按價格或類別等對它們進行排序。如果你想按名稱訂購這里是一個例子:

注意ArrayList是如何按項的name屬性排序的。 如果您不添加IComparable,那么當您使用sort方法時,它將引發錯誤。

在此輸入圖像描述

static void Main(string[] args)
    {
        ArrayList items = new ArrayList();
        items.Add(new Item("book", 12.32));
        items.Add(new Item("cd", 16.32));
        items.Add(new Item("bed", 124.2));
        items.Add(new Item("TV", 12.32));

        items.Sort();

        foreach (Item temp in items)
            Console.WriteLine("Name:{0} Price:{1}", temp.name, temp.price);
        Console.Read();            
    }


    class Item: IComparable
    {
        public string name;
        public double price;

        public Item(string _name, double _price)
        {
            this.name = _name;
            this.price = _price;
        }

        public int CompareTo(object obj)
        {   
            //note that I use the name property I may use a different one
            int temp = this.name.CompareTo(((Item)obj).name);
            return temp;
        }
    }

因為字符串按字母順序排序,而下划線字符排在數字字符之后。 您必須提供一個實施“自然順序”的比較器來實現所需的結果。

字符串比較算法一次比較每個字符 1排序前2 它跟隨12並不重要。

所以100會在2之前排序。 如果您不想要此行為,則需要一個處理此案例的比較算法。

正如其他人所說,默認情況下,元素將按字母順序排序。 解決方案是定義一個具體的java.util.Comparator類,並將其作為第二個參數傳遞給sort方法。 比較器需要從字符串中解析出前導整數並進行比較。

要使Collection.sort()任意排序,您可以使用

Collections.sort(List list, Comparator c)  

然后簡單地實現一個比較器,它拆分字符串並首先根據數字進行排序,然后對其余部分進行排序,或者您希望它進行排序。

每個人都已經指出,解釋是你的字符串排序為字符串,並且一些數字已經引導你注意自然順序字符串比較。 我只想補充說,自己編寫比較器是一個很好的練習,也是練習測試驅動開發的好機會。 我用它在Code Camp演示TDD; 幻燈片和代碼在這里

如上所述,您正在尋找實現自然排序的Comparator實現。 傑夫阿特伍德不久前寫了一篇關於自然分類的優秀文章 - 非常值得一讀。

如果您正在尋找Java實現,我發現這個實現很有用: http//www.davekoelle.com/alphanum.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM