Правильный способ для двусторонней сортировки - PullRequest
1 голос
/ 30 января 2012

У меня есть простое java pojo, которое выглядит так:

class MyClass
{
  public String getGroup();
  public String getTitle();
}

Теперь я хочу отсортировать список pojo MyClass по значениям, возвращаемым методом getTitle (). Спокойно, хотя использую мой собственный компаратор. Однако я хочу, чтобы экземпляры с одинаковым значением, возвращаемым getGroup (), следовали друг за другом. Теперь я сделал что-то вроде

.. compare(MyClass c1, MyClass c2)
{
  if (c1.getGroup().compareTo(c2.getGroup()) == 0)
  {
    return c1.getTitle().compareTo(c2.getTitle());
  }
  return c1.getGroup().compareTo(c2.getGroup());
}

Однако проблема этого кода в том, что он больше не сортируется в основном по заголовку, потому что я сначала сравниваю содержание групп, а не заголовок, поэтому группа, начинающаяся с «B», будет предшествовать началу группы. с "C", хотя его заголовок может стоять первым ... как правильно в первую очередь сортировать по заголовку, но также удостовериться, что группы "сгруппированы" вместе?

Пример данных:

MyClass 1 (group = "A", title="5")
MyClass 2 (group = "B", title="9")
MyClass 3 (group = "B", title="1")

Использование моего предыдущего кода приведет к

MyClass 1 (group = "A", title="5")
MyClass 3 (group = "B", title="1")
MyClass 2 (group = "B", title="9")

-> сортировка по группе, затем сортировка по заголовку

Но я хочу

MyClass 3 (group = "B", title="1")
MyClass 2 (group = "B", title="9")
MyClass 1 (group = "A", title="5")

-> сортировка по заголовку, но убедитесь, что каждая равная группа следует друг за другом, поэтому MyClass 1 с заголовком «5» следует за MyClass 2 с заголовком «9» ...

Ответы [ 4 ]

1 голос
/ 30 января 2012

Как правильно в первую очередь сортировать по заголовкам, но также удостовериться, что группы также объединены?

Чтобы отсортировать по названию и , а затем по группам, просто переключите getGroup() и getTitle() в любом месте вашего компаратора.

Вот альтернативная, упрощенная версия:

int compare(MyClass c1, MyClass c2)
{
  int cmp = c1.getTitle().compareTo(c2.getTitle());
  if (cmp == 0) {
    cmp = c1.getGroup().compareTo(c2.getGroup());
  }
  return cmp;
}

Если это не то, чего вы пытаетесь достичь, уточните ваши требования.

0 голосов
/ 15 августа 2012

Не может быть сделано с компаратором.Вам нужно просмотреть отсортированные заголовки, а затем отсортировать соответствующие группы по каждому непосещенному заголовку.Вот пример кода, который сортируется так, как вы хотели.

public class MyClass {
    private String  group;
    private String  title;

    public MyClass(String g, String t) {
        group=g;
        title=t;
    }

    static Comparator<MyClass>  TITLE_COMPARATOR    = 
            new Comparator<MyClass>() {
                    @Override
                    public int compare(MyClass c1, MyClass c2) {
                            return c1.title.compareTo(c2.title);
                    }
            };
    static Comparator<MyClass>  GROUP_COMPARATOR    = new Comparator<MyClass>() {
                    @Override
                    public int compare(MyClass c1, MyClass c2) {
                            return c1.group.compareTo(c2.group);
                    }
            };

    public static List<MyClass> sublist(List<MyClass> list, String group) {
            ArrayList<MyClass> ret = new ArrayList<MyClass>();
            for (MyClass mc : list)
                if (mc.group.equals(group))
                    ret.add(mc);
            return ret;
        }

public static void main(String[] argv) {
    ArrayList<MyClass> sorted = new ArrayList<MyClass>();

    ArrayList<MyClass> list = new ArrayList<MyClass>();
    list.add(new MyClass("A", "5"));
    list.add(new MyClass("B", "9"));
    list.add(new MyClass("B", "1"));
    Collections.sort(list, TITLE_COMPARATOR);
    Hashtable<String, Boolean> visited = new Hashtable<String, Boolean>();
    for (MyClass mc : list) {
        if (visited.get(mc.group) == null) {
            List<MyClass> sublist = sublist(list, mc.group);
            Collections.sort(sublist, GROUP_COMPARATOR);
            sorted.addAll(sublist);
            visited.put(mc.group, Boolean.TRUE);
        }
    }

    for (MyClass mc : sorted)
        System.out.println(mc.group + " " + mc.title);
}

}

0 голосов
/ 30 января 2012

Попробуйте использовать .getGroup вместо .getTitle (и наоборот) в вашем Comparator. Я думаю, что вы просто должны делать то, что делаете, наоборот.

0 голосов
/ 30 января 2012

Ваш вопрос не имеет смысла: быть «сгруппированным» означает сначала сортировку по группе , затем по title .

Это просто невозможно обойти.

Я думаю, вы действительно хотите то, что вы уже закодировали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...