简体   繁体   English

双向分拣的正确方法

[英]Proper way for two-way sorting

I've got a simple java pojo which looks like this: 我有一个简单的java pojo,看起来像这样:

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

Now what I want to do is to primarily sort a list of MyClass pojo by the values returned by the getTitle() method. 现在,我要做的主要是通过getTitle()方法返回的值对MyClass pojo列表进行排序。 Easy going though using my own comparator. 尽管使用我自己的比较器也很轻松。 However, what I want is that instances with the same value returned by getGroup() being followed by each other. 但是,我想要的是具有彼此相同的getGroup()返回值的实例。 Now what I did was something like 现在我所做的就像

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

However, the issue of this code is that it is no longer primarily sorted by the title because I do first compare the content of the groups, not the title, so a group starting with "B" would come before a group starting with "C" eventhough its title may come first.. what's the proper way to primarily sort by title but make sure groups are "groupped" together as well? 但是,此代码的问题在于,它不再主要按标题进行排序,因为我首先比较了组的内容,而不是标题,因此以“ B”开头的组会先于以“ C”开头的组“尽管其标题可能排在首位。主要按标题排序的正确方法是什么,但还要确保将组也“分组”在一起?

Sample data: 样本数据:

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

Using my previous code would end up in 使用我以前的代码将最终导致

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

-> sort by group, then sort by title ->按组排序,然后按标题排序

But I want 但我想要

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

-> sort by title but make sure each equal group follows each other that's why still MyClass 1 with title "5" comes after MyClass 2 with title "9"... ->按标题排序,但确保每个相等的组彼此跟随,这就是为什么标题为“ 5”的MyClass 1仍然排在标题为“ 9”的MyClass 2之后...

what's the proper way to primarily sort by title but make sure groups are "groupped" together as well? 什么是主要按标题排序的正确方法,但还要确保将组也“分组”在一起?

To sort by title and then by group, just switch getGroup() and getTitle() everywhere in your comparator. 要按标题排序, 然后按组排序,只需在比较器中的任何位置切换getGroup()getTitle()

Here is an alternative, simplified, version: 这是一个替代的简化版本:

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

If that's not what you are trying to achieve, please clarify your requirements. 如果这不是您要实现的目标,请阐明您的要求。

Can't be done with a Comparator. 比较器无法完成。 You need to run through the sorted titles, then for each unvisited title sort the corresponding groups. 您需要遍历已排序的标题,然后针对每个未访问的标题对相应的组进行排序。 Here's some sample code that sorts like the way you wanted. 这是一些示例代码,其排序方式与您想要的方式类似。

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);
}

} }

Your question makes no sense: Being "grouped together" means sorting by group first, then by title . 您的问题毫无意义:“分组在一起”是指先按排序,然后按标题排序。

There's just no getting around it. 只是没有解决。

I think you really want what you already coded. 我认为您真的想要您已经编写的代码。

Try using .getGroup instead of .getTitle (and vice-versa) in your Comparator. 尝试在比较器中使用.getGroup而不是.getTitle(反之亦然)。 I think you just should do what you're doing the other way around. 我认为您应该反过来做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM