2015-04-29 2 views
1

Вот код, который я до сих пор:Как создать пользовательский компаратор для сортировки системы нумерации

package Demo; 

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.Comparator; 

public class Demo { 

    public static void main(String[] args) { 

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

     list.add("3.3.x"); 
     list.add("1.2.x"); 
     list.add("2.3.x"); 

     VersionComparator x = new VersionComparator(); 

     Collections.sort(list, x); 

     for(String str : list) 
      System.out.println(str); 

    } 

    static class VersionComparator implements Comparator { 
     public int compare(String str1, String str2) { 

      String firstNumberStringOne = str1.split(".")[0]; 
      String firstNumberStringTwo = str2.split(".")[0]; 
      String secondNumberStringOne = str1.split(".")[1]; 
      String secondNumberStringTwo = str2.split(".")[1]; 

      return; 
     } 

     @Override 
     public int compare(Object o1, Object o2) { 
      // TODO Auto-generated method stub 
      return 0; 
     } 
    } 
} 

Я хотел бы, чтобы отсортировать элементы в моем списке под первым номером, который появляется перед периодом. Если эти два числа равны, то перейдите ко второму числу и сравните эти числа. И если равные просто вернут их.

Я не уверен, как использовать компаратор. Я попытался реализовать его, и компилятор жаловался, что мне нужно добавить второй метод сравнения с переопределением. Я также не знаю, как сделать сравнение с точки зрения того, как оно возвращается. Я понимаю, что если его равно, то он возвращает 0, а его меньше, чем тогда, он возвращает -1 и больше, чем 1. Но с точки зрения кодирования я теряюсь относительно того, как программа знает, как ее сортировать.

+1

'раскол ("")' не выглядит хорошо. Пожалуйста, прочитайте один из: http://stackoverflow.com/q/14833008/1393766 http://stackoverflow.com/q/7935858/1393766 http://stackoverflow.com/q/3387622/1393766 http: // stackoverflow. com/q/2755945/1393766 – Pshemo

ответ

0

Есть несколько проблем с кодом:

  1. Вы используете сырые типы так в

    class VersionComparator implements Comparator 
    

    компаратора Comparator<T> будет пытаться используйте Object как T, что означает, что его метод сравнения, объявленный как compare(T t1, T t2), будет compare(Object t1, Object o2). Так что если вы хотите сравнить Strings грим компаратора для струнных инструментов, как

    class VersionComparator implements Comparator<String> 
    

    , который теперь будет знать, что T является String так сравнивая метод теперь будет выглядеть compare(Object t1, Object o2){..}

  2. Когда вы звоните split(".") вы не Расщепление на точечном, но на любом символе (потому что использует регулярное выражение, а в regex . представляет любой символ рядом с разделителем строк \n и \r). Из-за этого при запуске вы получите массив пустых элементов, которые затем будут очищены, потому что split удаляет пустые элементы. Больше информации здесь: https://stackoverflow.com/a/21790319/1393766.

    Чтобы решить эту проблему, вам необходимо сбежать от ., например, с помощью "\\.".

Это должно охватывать основные проблемы в вашем коде. Но если вы хотите создать приятное решение, подумайте об избежании сортировки Strings, а скорее о ваших собственных классах Version.
Преимущество этого подхода заключается в том, что вам не придется анализировать вашу строку в int каждый раз, когда вы хотите сравнить две строки (что может быть дорогостоящим), но вы сможете сохранить разборную версию "1.2.3" как массив [1, 2, 3] и повторно использовать его при необходимости.
Также класс Version может реализовать Comparable<Vector>, чтобы обеспечить метод сравнения по умолчанию.

Так что ваш код может выглядеть как:

class Version implements Comparable<Version> { 

    private String versionStr; 
    private int[] arr; 

    public String getVersionStr() { return versionStr; } 

    @Override public String toString() { return versionStr; } 

    @Override 
    public int compareTo(Version o) { 

     int result = Integer.compare(arr[0], o.arr[0]); 

     if (result != 0) 
      return result; 

     return Integer.compare(arr[1], o.arr[1]); 
    } 

    public Version(String versionStr) { 
     this.versionStr = versionStr; 
     this.arr = Stream.of(versionStr.split("\\.")) 
       .limit(2)//get only two first elements 
       .mapToInt(Integer::parseInt)//convert String to int 
       .toArray();//return array of integers 
    } 

} 

class Demo { 

    public static void main(String[] args) { 

     List<Version> list = new ArrayList<Version>(); 

     list.add(new Version("3.3.x")); 
     list.add(new Version("1.2.x")); 
     list.add(new Version("1.11.x")); 
     list.add(new Version("2.3.x")); 

     Collections.sort(list); 

     for (Version str : list) 
      System.out.println(str); 
    } 
} 
2

Ваш VersionComparator класс реализует необработанный вид интерфейса Comparator, где метод compare займет 2 Object сек вместо 2 String с.

Внедрите интерфейс, указав String в качестве параметра типа. Затем компилятор распознает ваш метод compare, принимая String s в качестве параметров, соответствующих правильной реализации интерфейса. Вам не нужен метод compare, принимающий Object s.

static class VersionComparator implements Comparator<String> { 

Вы, конечно, нужно реализовать логику сравнения в вашем compare method, возвращая int менее 0, 0, или больше, чем 0, если str1 сравнивает меньше, равно или больше, то str2 в соответствии с вашими пользовательский порядок сортировки.

0
public static void main(String[] args) { 
    ArrayList<String> list = new ArrayList<String>(); 
    list.add("3.3.x"); 
    list.add("1.2.x"); 
    list.add("1.11.x"); 
    list.add("1.1.x"); 
    list.add("2.3.x"); 

    Collections.sort(list, new VersionComparator()); 

    for(String str : list) 
     System.out.println(str); 

} 

static class VersionComparator implements Comparator<String> { 
    //Temporary Cache Map to hold Split String value. String as Key and Split String array as value is this in this map. 
    Map<String, String[]> mCacheMap = new HashMap<>(); 

    @Override 
    public int compare(String string1, String string2) { 

     if(!mCacheMap.containsKey(string1)){ 
      //Put Split String of string1 to map if it does not contain it. 
      mCacheMap.put(string1, string1.split("\\.")); 
     } 
     if(!mCacheMap.containsKey(string2)){ 
      //Put Split String of string2 to map if it does not contain it. 
      mCacheMap.put(string2, string2.split("\\.")); 
     } 
     //Get First Digit of first string1 from Map 
     Integer string1Val1 = Integer.valueOf(mCacheMap.get(string1)[0]); 
     //Get First Digit of second string2 from Map    
     Integer string2Val1 = Integer.valueOf(mCacheMap.get(string2)[0]); 

     //Compare Both Digit. compareTo Method return a negative integer, zero, or a positive integer as first Integer value is less than, equal to, or greater than the seconf Integer value. 
     int cmp = string1Val1.compareTo(string2Val1); 

     if(cmp != 0){ 
      return cmp; 
     }else { 
      //If First digit of both string is same compare second digit. 
      Integer string1Val2 = Integer.valueOf(mCacheMap.get(string1)[1]); 
      Integer string2Val2 = Integer.valueOf(mCacheMap.get(string2)[1]); 
      return string1Val2.compareTo(string2Val2); 
     } 

    } 
} 

Результаты:

1.1.x 
1.2.x 
1.11.x 
2.3.x 
3.3.x 
+0

Я опубликую Update Now. –

+0

@Pshemo Не могли бы вы пересмотреть мой обновленный ответ. –

+0

Работает лучше. Теперь вам просто нужно объяснить OP, что было не так с его/ее подходом и почему/как работает ваш подход. – Pshemo

Смежные вопросы