2012-01-24 3 views
3

Я hava ArrayList из значений String (они должны быть отформатированы как таковые), которые мне нужно отсортировать по годам. Список выглядит следующим образом:Сортировка ArrayList строк с использованием regex

01-05-2011 
11-24-2011 
01-12-2012 
... 

Я в настоящее время у них отсортированы в алфавитном порядке по месяцам, но мне было интересно, как я могу разобраться в этом ArrayList цепочек в год.

ответ

7
Collections.sort(
    myList, new Comparator<String>() { 
     @Override 
     public int compare(String a, String b) { 
     // If a is "11-24-2012", then aLastDash points 
     // here ---------^. 
     int aLastDash = a.lastIndexOf("-"); 
     int bLastDash = b.lastIndexOf("-"); 
     return a.substring(aLastDash+1).compareTo(
       b.substring(bLastDash+1)); 
     } 
    }); 

Collections.sort принимает Comparator, который определяет, как сравнивать два значения списка. Значения в вашем случае: String s. Вы можете просто сравнить последние 4 цифры каждой строки лексикографически, и все готово.

Collections.sortstable, так что если ваши строки уже отсортированы по месяцам, и вы сортируете по годам, группы строк с тем же годом по-прежнему будут отсортированы по месяцам.

В идеале, вы должны преобразовать свой список в список чего-то другого, кроме строк, например, даты дат Joda. Сейчас этот код stringly typed. Чем раньше вы вносите данные и принуждаете их к значимым объектам, тем меньше ваш код должен делать входные предположения тем меньше строк кода, которые вы должны отлаживать, когда ваши предположения не совсем удержаны.

4

Я бы не использовал регулярное выражение для этого - в основном вы должны реализовать Comparator<String>, чтобы сравнить любые две строки. Вы могли бы это сделать, просто переставив биты строки (например, в формат yyyyMMdd), а затем выполнив лексикографическое сравнение, или вы можете проанализировать строку как дату и сравнить две даты.

В любом случае, вы должны передать компаратор в Collections.sort().

Обратите внимание, что это предложение будет сортировать их полностью - так по годам, затем месяцам, а затем и день. Если вы просто сортировать по годам, они все еще не будут в реальном хронологическом порядке. Я лично поступил бы прямо, чтобы сделать это полностью в хронологическом порядке, поскольку это, скорее всего, вызовет меньше сюрпризов позже.

+0

@John: Мне было интересно: 1) Как вы решаете, когда регулярное выражение подход является предпочтительным способом 2) Я не следовать? часть «перестановки битов строки и последующего выполнения лексикографического сравнения» – Cratylus

+0

Он имел в виду: сначала напишите ваши даты как 2011-05-01, а не 01-05-2011, затем используйте естественный лексикографический порядок. Это то, что предлагает @dasblinkenlight. Теперь вы можете сделать это в своем списке или в вашем компараторе (но сравнение будет медленнее). И я согласен, это был бы самый разумный способ сортировки ваших дат. – Guillaume

+0

@ user384706: Я бы использовал регулярное выражение, когда Я хотел выполнить сопоставление образцов. Здесь нет реального соответствия шаблону - на шаблоне есть сравнение *, но это не одно и то же. –

1

Используйте Collections.sort и создайте Comparator, который использует регулярные выражения.

2

Если установлены при помощи регулярных выражений, превратить вашу строку, как это:

String toCompare = monthDayYearString.replaceAll(
    "(\\d\\d)-(\\d\\d)-(\\d\\d\\d\\d)" 
, "$3$1$2" 
); 

Это выражение отражает элементы вашей даты и переупорядочивают их принести медленнее изменяющие элементы ближе к началу Струна. Теперь строки можно сортировать по дате в алфавитном порядке.

1

Я объединил два из предложенных решений здесь ..

Arrays.sort(new String[] {}, new Comparator<String>() { 
     private final Pattern p = Pattern.compile("(\\d\\d)-(\\d\\d)-(\\d\\d\\d\\d)"); 

     @Override 
     public int compare(String o1, String o2) { 
      Matcher m1 = p.matcher(o1); 
      Matcher m2 = p.matcher(o2); 

      int compareYear = m1.group(3).compareTo(m2.group(3)); 
      if (compareYear == 0) { 
       int compareMonth = m1.group(1).compareTo(m2.group(1)); 
       if (compareMonth == 0) { 
        return m1.group(2).compareTo(m2.group(2)); 
       } else { 
        return compareMonth; 
       } 

      } else { 
       return compareYear; 
      } 

     } 
    }); 
Смежные вопросы