Использование коллекций для сортировки значений - PullRequest
3 голосов
/ 15 декабря 2011

Использование коллекций для сортировки - изящно, для меня это намного лучше, чем использование Comparator, поскольку у меня несколько одинаковых значений, и я бы предпочел, чтобы их не просто выбрасывали в корзину. Но у Коллекций есть своя собственная проблема: кажется, что повторяющиеся числа групп 2+ меньше, чем их фактические меньшие встречные части

В примере есть эти ключи и значения ("katy 1", "mark 9", "john 2", "alice 11", "josiah 22", "chris 44"), и он сортирует их следующим образом

Алиса 11 Кэти 1 Джон 2 Иосия 22 Крис 44 оценка 9

Вместо правильного заказа Кэти 1 Джон 2 оценка 9 Алиса 11 Иосия 22 оценка 44

Как я могу это исправить?

Ответы [ 7 ]

5 голосов
/ 15 декабря 2011

Так как вы передаете строки, коллекция не может сказать, как вы хотите, чтобы эти строки интерпретировались (то есть сортировать по числу, присутствующему в строке). Вы должны быть более явным.

У вас есть два варианта:

Опция 1 : создать новый тип данных для инкапсуляции имени и числа и выполнить сравнение по номеру:

public class Person implements Comparable<Person> {

     private String name;
     private int number;

     public Person(String name, int number) {
         this.name = name;
         this.number = number;
     }

     public int compareTo(Person p) {
         return this.number.compareTo(p.number);
     }
}

Тогда:

 List<Person> persons = new ArrayList<Person>();
 persons.add(new Person("alice", 11));
 persons.add(new Person("katy", 1));
 // etc.
 Collections.sort(persons);

Вариант 2 : превратить строку в пару ключ-значение и поместить ее в TreeMap, который автоматически сохраняет значения, отсортированные по ключу:

 TreeMap<Integer, String> map = new TreeMap<Integer, String>();
 map.put(11, "alice");
 map.put(1, "katy");
 // etc.
2 голосов
/ 15 декабря 2011
  1. Сохраните данные как Map<String, Integer> - не объединяйте два типа данных в одну строку.
  2. Получите набор записей в список и отсортируйте его
  3. Поместите отсортированный набор записей в упорядоченную Карту

Вот код, который сделает это:

public static void main(String[] args) {
    // Set up and load the map
    Map<String, Integer> nameAgeMap = new HashMap<String, Integer>();
    nameAgeMap.put("katy", 1);
    nameAgeMap.put("chris", 44);
    nameAgeMap.put("alice", 11);
    nameAgeMap.put("josiah", 22);
    nameAgeMap.put("john", 2);

    // Create-and-load a List of entries
    List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>(nameAgeMap.entrySet());
    // Sort the list using a custom Comparator that compares the ages
    Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
        public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
            return o1.getValue().compareTo(o2.getValue());
        }});

    // Load the entries into a Map that preserves insert order
    Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
    for (Map.Entry<String, Integer> entry : entries)
        sortedMap.put(entry.getKey(), entry.getValue());

    // All done - let's see what we got
    System.out.println(sortedMap);
}

Вывод:

{katy=1, john=2, alice=11, josiah=22, chris=44}
1 голос
/ 07 октября 2013

Сортировка логики для значений $ в порядке возрастания.если вам это нужно в порядке убывания, пожалуйста, поменяйте местами переменные i1 и i2

public static void main(String[] args) {



    List<String> l_oTestList = new ArrayList<String>();
    l_oTestList.add("$10000 - $12000");
    l_oTestList.add("$50 - $100");
    l_oTestList.add("$10000 - $12000");
    l_oTestList.add("$100 - $150");
    l_oTestList.add("$150 - $200");
    l_oTestList.add("$200 - $250");
    l_oTestList.add("$0 - $10");
    l_oTestList.add("$10 - $20");
    l_oTestList.add("$20 - $50");
    l_oTestList.add("$250 - $500");
    l_oTestList.add("$500 - $750");
    l_oTestList.add("$750 - $1000");
    l_oTestList.add("$1000 - $1250");
    l_oTestList.add("$1250 - $10000");
    List<String> l_oTestList1 = sort(l_oTestList);
    System.out.println(l_oTestList1.toString());
}

private static List<String> sort(List<String> pTestList) {
    Collections.sort(pTestList, new Comparator<String>() {
        public int compare(String o1, String o2) {
            Integer i1 = Integer.parseInt(o1.replace("$", "").substring(0,o1.indexOf("-")-2).trim());
            Integer i2 = Integer.parseInt(o2.replace("$", "").substring(0,o2.indexOf("-")-2).trim());
            return (i2 > i1 ? -1 : (i2 == i1 ? 0 : 1));
        }
    });
    return pTestList;
}
1 голос
/ 15 декабря 2011

Я думаю, вам нужно создать класс Person, который реализует интерфейс Comparable

class Person implements Comparable<Person >{

       String name;
       Integer number;
       public int compareTo(Person o) {

        return number.compareTo(o.number);
    }

}
0 голосов
/ 15 декабря 2011

проверьте этот пример

Редактировать

public static void main(String arg[]){

    List<String> l = Arrays.asList(new String[]{"katy 1","mark 9","john 2","alice 11","josiah 22","chris 44"});

    Collections.sort(l, new Comparator<String>() {
        public int compare(String x, String y) {
            Integer a = Integer.parseInt(x.substring(x.indexOf(" ")).trim());
            Integer b = Integer.parseInt(y.substring(y.indexOf(" ")).trim());
            return a.compareTo(b);
        }
    });
    System.out.println(l.toString());
}
0 голосов
/ 15 декабря 2011

Вам нужно написать свой собственный компаратор. Если вы хотите сравнить строку как число, вам нужно преобразовать ее в число. В противном случае "22" <"4", хотя 22> 4.

Однако я не вижу, как вы получаете первый заказ с компаратором по умолчанию.

0 голосов
/ 15 декабря 2011

Лучшим вариантом будет рефакторинг вашего кода для разделения строк и целых чисел.

Если вы не можете или не хотите этого, вы должны предоставить свой собственный компаратор.Что-то вроде

@Override
public int compare(String o1, String o2) {
    Integer i1 = Integer.parseInt(o1.replaceAll("[^0-9]", ""));
    Integer i2 = Integer.parseInt(o2.replaceAll("[^0-9]", ""));
    return i1.compareTo(i2);
}

Тогда вы можете использовать Collections.sort(List, Comparator)

List<String> list; // ...
Collections.sort(list, new YourComparator());
...