2010-03-27 166 views

回答

13
public static void main(String[] args) 
    { 
    String string = "3 42 \n 11 \t 7 dsfss 365   \r 1"; 
    String[] numbers = string.split("\\D+"); 
    Arrays.sort(numbers, new Comparator<String>() 
    { 
     public int compare(String s1, String s2) 
     { 
     return Integer.valueOf(s1).compareTo(Integer.valueOf(s2)); 
     } 
    }); 
    System.out.println(Arrays.toString(numbers)); 
    } 
+1

偉大的解決方案,雖然它會打破,如果有一個非數字在那裏:) – extraneon 2010-03-27 12:46:59

+1

我不知道它是否有任何實際區別,但我認爲這是建議使用Integer.valueOf(S),而不是新的整數( S)。據推測,valueOf()調用會對實例進行一些內部緩存。 – 2010-03-28 00:41:53

+0

@gregcase好的建議,我編輯了答案。 – eljenso 2010-03-28 10:31:09

3

是相當病態的你的問題,但這裏有幾件事情,你應該知道:

因此,鑑於String[] sarr,如果你想字典順序(即"1" < "10" < "2"),只需Arrays.sort(sarr);作品排序。字符串是否包含數字並不重要。

如果您想對字符串進行排序(如"1" < "2" < "10"),則需要將字符串轉換爲數字值。取決於這些數字的範圍,Integer.parseInt可能會這樣做;否則,您始終可以使用BigInteger

我們假設需要BigInteger

現在你有兩個選擇:

  • 轉換String[]BigInteger[],則由於BigInteger implements Comparable<BigInteger>,您可以使用它的自然順序使用Arrays.sort。然後,您可以將排序的BigInteger[]轉換回String[]

  • String轉換爲BigInteger「適時」用於通過自定義Comparator<String>進行比較。由於Arrays.sort使用基於比較的mergesort,因此可以預期O(N log N)比較,因此可以進行多次轉換。

14

一個通用的解決方案是使用所謂的「自然順序比較器」。

下面是一個例子:

http://pierre-luc.paour.9online.fr/NaturalOrderComparator.java

自然順序實際上是在情況很重要,因爲一個字符串可能包含數字的運行和你想要的東西,按字母順序上的字母,但數字排序的數字。例如,Windows資源管理器的現代版本使用它來排序文件名。根據版本字符串選擇最新版本的庫(即「1.2.3」與「1.20.1」相比)也非常方便。

如果你的字符串真的只包含數字(就像你放在描述中一樣),那麼你最好不要使用字符串 - 而是用Integer對象創建和使用。

注意:上面的鏈接似乎已被打破。該代碼是非常有用,我要在這裏發佈:

/* 
* <copyright> 
* 
* Copyright 1997-2007 BBNT Solutions, LLC 
* under sponsorship of the Defense Advanced Research Projects 
* Agency (DARPA). 
* 
* You can redistribute this software and/or modify it under the 
* terms of the Cougaar Open Source License as published on the 
* Cougaar Open Source Website (www.cougaar.org). 
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
* 
* </copyright> 
*/ 
/* 
NaturalOrderComparator.java -- Perform 'natural order' comparisons of strings in Java. 
Copyright (C) 2003 by Pierre-Luc Paour <[email protected]> 

Based on the C version by Martin Pool, of which this is more or less a straight conversion. 
Copyright (C) 2000 by Martin Pool <[email protected]> 

This software is provided 'as-is', without any express or implied 
warranty. In no event will the authors be held liable for any damages 
arising from the use of this software. 

Permission is granted to anyone to use this software for any purpose, 
including commercial applications, and to alter it and redistribute it 
freely, subject to the following restrictions: 

1. The origin of this software must not be misrepresented; you must not 
claim that you wrote the original software. If you use this software 
in a product, an acknowledgment in the product documentation would be 
appreciated but is not required. 
2. Altered source versions must be plainly marked as such, and must not be 
misrepresented as being the original software. 
3. This notice may not be removed or altered from any source distribution. 
*/ 
package org.cougaar.util; 

//CHANGES: KD - added case sensitive ordering capability 
// Made comparison so it doesn't treat spaces as special characters 

//CHANGES: 
// set package to "org.cougaar.util" 
// replaced "import java.util.*" with explicit imports, 
// added "main" file reader support 

import java.util.Comparator; 

/** 
* A sorting comparator to sort strings numerically, 
* ie [1, 2, 10], as opposed to [1, 10, 2]. 
*/ 
public final class NaturalOrderComparator<T> implements Comparator<T> { 

    public static final Comparator<String> NUMERICAL_ORDER = new NaturalOrderComparator<String>(false); 
    public static final Comparator<String> CASEINSENSITIVE_NUMERICAL_ORDER = new NaturalOrderComparator<String>(true); 

    private final boolean caseInsensitive; 

    private NaturalOrderComparator(boolean caseInsensitive) { 
     this.caseInsensitive = caseInsensitive; 
    } 

    int compareRight(String a, String b) { 
     int bias = 0; 
     int ia = 0; 
     int ib = 0; 

     // The longest run of digits wins. That aside, the greatest 
     // value wins, but we can't know that it will until we've scanned 
     // both numbers to know that they have the same magnitude, so we 
     // remember it in BIAS. 
     for (;; ia++, ib++) { 
      char ca = charAt(a, ia); 
      char cb = charAt(b, ib); 

      if (!Character.isDigit(ca) && !Character.isDigit(cb)) { 
       return bias; 
      } else if (!Character.isDigit(ca)) { 
       return -1; 
      } else if (!Character.isDigit(cb)) { 
       return +1; 
      } else if (ca < cb) { 
       if (bias == 0) { 
        bias = -1; 
       } 
      } else if (ca > cb) { 
       if (bias == 0) 
        bias = +1; 
      } else if (ca == 0 && cb == 0) { 
       return bias; 
      } 
     } 
    } 

    public int compare(T o1, T o2) { 
     String a = o1.toString(); 
     String b = o2.toString(); 

     int ia = 0, ib = 0; 
     int nza = 0, nzb = 0; 
     char ca, cb; 
     int result; 

     while (true) { 
      // only count the number of zeroes leading the last number compared 
      nza = nzb = 0; 

      ca = charAt(a, ia); 
      cb = charAt(b, ib); 

      // skip over leading zeros 
      while (ca == '0') { 
       if (ca == '0') { 
        nza++; 
       } else { 
        // only count consecutive zeroes 
        nza = 0; 
       } 

       // if the next character isn't a digit, then we've had a run of only zeros 
       // we still need to treat this as a 0 for comparison purposes 
       if (!Character.isDigit(charAt(a, ia+1))) 
        break; 

       ca = charAt(a, ++ia); 
      } 

      while (cb == '0') { 
       if (cb == '0') { 
        nzb++; 
       } else { 
        // only count consecutive zeroes 
        nzb = 0; 
       } 

       // if the next character isn't a digit, then we've had a run of only zeros 
       // we still need to treat this as a 0 for comparison purposes 
       if (!Character.isDigit(charAt(b, ib+1))) 
        break; 

       cb = charAt(b, ++ib); 
      } 

      // process run of digits 
      if (Character.isDigit(ca) && Character.isDigit(cb)) { 
       if ((result = compareRight(a.substring(ia), b 
         .substring(ib))) != 0) { 
        return result; 
       } 
      } 

      if (ca == 0 && cb == 0) { 
       // The strings compare the same. Perhaps the caller 
       // will want to call strcmp to break the tie. 
       return nza - nzb; 
      } 

      if (ca < cb) { 
       return -1; 
      } else if (ca > cb) { 
       return +1; 
      } 

      ++ia; 
      ++ib; 
     } 
    } 

    private char charAt(String s, int i) { 
     if (i >= s.length()) { 
      return 0; 
     } else { 
      return caseInsensitive ? Character.toUpperCase(s.charAt(i)) : s.charAt(i); 
     } 
    } 


} 
+0

這特別適合用於人類消費的數據排序(尤其是如果將案例差異視爲二階差異),因爲它產生的訂單往往與非技術用戶想象訂購的工作方式相匹配。 – 2010-03-28 10:34:44

+0

鏈接被破壞,可以提供另一個鏈接 – sara 2013-01-28 10:58:00

+1

@sara代碼張貼在上面。請享用。 – 2013-02-13 04:22:19

0

以「事」根據一些順序排序的方式是創建知道一個比較,其中任何兩件事情,首先根據順序,或讓「事物」本身實現Comparable接口,因此您不需要比較器。

如果你的工作是整理爲整數,然後再考慮轉換整數和然後排序爲Integer類已經實現了媲美。

0

在Java 8中,我們有很好的解決方案

public static List<String> sortAsNumbers(Collection<String> collection) { 
    return collection 
      .stream() 
      .map(Integer::valueOf) 
      .sorted() 
      .map(String::valueOf) 
      .collect(Collectors.toList()); 
} 
0
static final Comparator<Object> COMPARADOR = new Comparator<Object>() { 
    public int compare(Object o1, Object o2) { 
     double numero1; 
     double numero2; 
     try { 
      numero1 = Double.parseDouble(o1.toString()); 
      numero2 = Double.parseDouble(o2.toString()); 
      return Double.compare(numero1, numero2); 
     } catch (Exception e) { 
      return o1.toString().compareTo(o2.toString()); 
     } 
    } 
}; 

... 的ArrayList listaDeDatos; listaDeDatos.sort(COMPARADOR);

相關問題