【问题标题】:How to perform a series of sort operation on arraylist (multiple sort criteria)如何对arraylist进行一系列排序操作(多种排序条件)
【发布时间】:2012-01-02 23:35:37
【问题描述】:

我有一个对象数组列表,我想在这个列表上运行一系列排序操作。例如,我想按名称对它们进行排序,如果两个名称相同,则按 id 对它们进行排序。

我该如何实现它?

这是我的代码

Comparator<Ticket> mc;
mc = new TicketIdComparator();
Collections.sort(tickets, mc);


final class TicketIdComparator implements Comparator<Ticket>

{

    @Override
    public int compare(Ticket ticket1, Ticket ticket2) {
        String TicketId1 = ((Ticket) ticket1).getNumber();
        String TickedId2 = ((Ticket) ticket2).getNumber();

        int num1=Integer.parseInt(TicketId1);
        int num2 =Integer.parseInt(TickedId2);

        if (num1<num2)
            return 1;
        if (num1>num2)
            return -1;
        return 0;



    }
}

此代码按id 排序,但我想再次按name 排序

【问题讨论】:

标签: java sorting collections arraylist comparator


【解决方案1】:

您可以从比较器集合中编写比较器。

public static <T extends Comparable<T>> Comparator<T> comparatorFrom(final Comparator<T>... comparators) {
    return new Comparator<T>() {
        @Override
        public int compare(T o1, T o2) {
            for (Comparator<T> comparator : comparators) {
                final int cmp = comparator.compare(o1, o2);
                if (cmp != 0) return cmp;
            }
            return 0;
        }
    };
}

// you can then use
Arrays.sort(list, comparatorFrom(comp1, comp2, comp3, comp4));

【讨论】:

  • 我收到来自 Eclipse 的警告:“类型安全:通过可变参数比较器造成的潜在堆污染”,我应该添加 @SafeVarargs 吗?
  • @ChristopheRoussy 这似乎是 IDE 特定的警告。我希望 Eclipse 有一个建议的解决方案,比如适当的 \@SuppressWarning
  • 你的意思是像@SuppressWarnings("unchecked") final Comparator&lt;T&gt;... comparators 这样的东西吗,其实Eclipse 提出了多种解决方案。
  • @ChristopheRoussy 在这种情况下,我可能会关注其中之一。 IntelliJ 不会抱怨,事实上没有问题恕我直言,这只是让您的 IDE 满意的问题。
【解决方案2】:
  Collections.sort(myList, new Comparator() {

     @Override
     public int compare(Object o1, Object o2)
     {
        // write your ordering code here
        return 0;
     }

  });

只需填写您想要的比较代码,Java 将为您处理排序。

编辑更新的问题:

Comparator<Ticket> mc;
mc = new TicketIdComparator();
Collections.sort(tickets, mc);


final class TicketIdComparator implements Comparator<Ticket>

{

    @Override
    public int compare(Ticket ticket1, Ticket ticket2) {
        String TicketId1 = ((Ticket) ticket1).getNumber();
        String TickedId2 = ((Ticket) ticket2).getNumber();

        int num1=Integer.parseInt(TicketId1);
        int num2 =Integer.parseInt(TickedId2);

        if (num1<num2)
            return 1;
        else if (num1>num2)
            return -1;
        else
            return ticket1.getName().compare(ticket2.getName());
    }
}

【讨论】:

  • 请看我的编辑,这是一种工作,现在我应该怎么做,如果我想在这个排序列表上根据名称执行排序
【解决方案3】:

正如您所说,与您已经编写的代码类似,您将创建一个实现 Ticket 的 Comparator 接口的类。首先,您使用字符串比较器比较票证的名称,如果结果为 0(同名),那么您将在同一个比较器中按 id 进行比较。

确保字符串比较器在之前进行修剪(删除前后空格)并且可能忽略大小写,这取决于你。

如果您想要某种概括,那么您可以编写一个装饰器比较器来调用更具体的比较器。如果您想了解更多相关信息,请告诉我。

【讨论】:

  • Luciano:我从 Jordan Bentley 那里得到了解决方案,但我想我想要一个更通用的解决方案。因为有时我想按名称排序,有时按摘要排序,有时按 id 排序......目前正在为每个比较器制作单独的比较器......有什么办法,我可以从一个比较器做。
  • 我本来打算写代码,然后我决定搜索:) 这个问题的前两个答案stackoverflow.com/questions/1421322/… 将帮助您了解按多个字段进行比较的想法。如果你想用一个实用程序库来做,那么看看这个问题:stackoverflow.com/questions/6081384/…
【解决方案4】:

Collections.sort(myList, new Comparator() {

 @Override
 public int compare(Object o1, Object o2)
 {
    // write your ordering code here for sorting list by id
    return 0;
 }

});

按 id 排序的列表

Collections.sort(myList, new Comparator() {

 @Override
 public int compare(Object o1, Object o2)
 {
    // write your ordering code here for sorting list by name
    return 0;
 }

});

它会给出按名称排序的列表

【讨论】:

    【解决方案5】:

    使用 Java 8,您可以使用 lambdas,根据 Peter Lawrey 的回答,您可以做一些漂亮的事情:

            Collections.sort(users, comparatorFrom(
    
                        (final User u1, final User u2) -> u1.getDomain().getFirstName()
                            .compareTo(u2.getFirstName()),
    
                        (final User u1, final User u2) -> u1.getLastName().compareTo(u2.getLastName()),
    
                        ...more comparators here...
    
                   ));
    

    【讨论】:

      【解决方案6】:

      您需要使用稳定的排序算法,然后先按 ID 排序,然后按名称排序。

      查看this comparison of algorithms 找到适合您需求的。

      【讨论】:

      • 无需两次排序:您可以一步比较id和name(如示例)。如果 ID 相同,则比较名称。见乔丹的回答
      • @Matteo 好吧,同时问题中还有更多信息。第一个版本甚至没有提到编程语言。只是按两个值对列表进行排序,并且以我提到的方式进行两次排序是一种可能的解决方案。
      猜你喜欢
      • 1970-01-01
      • 2012-02-03
      • 2021-05-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 2011-04-11
      • 1970-01-01
      相关资源
      最近更新 更多