【问题标题】:sort an ArrayList with multiple conditions对具有多个条件的 ArrayList 进行排序
【发布时间】:2016-12-30 21:34:41
【问题描述】:

假设我有一个数组列表MyArrayList<MYObject>

myObject 类看起来像:

public class myObject
{
      String name;
      Int age;
      String : city;
}

我的虚拟数据如下所示:

name : martin ,  age : 20 , city : NY
name : felix ,  age : 19 , city : LA
name : brian ,  age : 21 , city : NY
name : brian ,  age : 19 , city : NY

现在我想按此顺序对 myArraylist(其中包含上述数据)进行排序 -

name : felix , lastname : 19 , city : LA
name : brian , lastname : 21 , city : NY
name : martin , lastname : 20 , city : NY
name : brian , lastname : 19 , city : NY

如您所见,上述数据以两种方式排序 - 首先按 cities 然后再次按 age 所以这就是我想要做的,我想要排序arrayList 按顺序然后我想通过保持第一个顺序以另一个顺序排序

谁知道我该怎么做??那么请告诉我

如果我的问题不够清楚,请告诉我,我会解决的

【问题讨论】:

  • 使用 orderby...它是一种稳定的排序方式,所以第二次排序时会保留第一次排序的顺序
  • 所以你的意思是我应该做第一次排序然后在第二次排序我必须使用orderby ??
  • 可以的
  • 根据 java,集合的默认排序是稳定的,因此您可以进行双重排序,它应该可以解决问题。我赶紧扫了一眼,以为是c#。

标签: java sorting arraylist


【解决方案1】:

您可以创建一个比较器,首先按城市进行比较,然后按年龄进行比较。像这样的:

Comparator<MyObject> comparator = new Comparator<MyObject>(){
    @Override
    public int compare(final MyObject o1, final MyObject o2){
       if(!o1.getCity().equals(o2.getCity())){
          return o1.getCity().compareTo(o2.getCity());
       }else{
          return o1.getAge().compareTo(o2.getAge());
        }
    }
  };

Collections.sort(myArrayList,comparator);

编辑:

我使用了 Integer 类的“compareTo”方法,您不能在 int 原始类型上调用该方法。如果你使用int 作为年龄,你可以写一个if 语句进行比较。

【讨论】:

    【解决方案2】:

    首先,类应该有一个描述性的名称,并且类名应该以大写字符开头。所以我会打电话给你的班级Person

    您需要创建一个自定义Comparator 以供排序实用程序使用。

    对于可重复使用的解决方案,您可以使用Bean ComparatorGroup Comparator

    1. BeanComparator 允许您对对象中的任何属性进行排序

    2. GroupComparator 允许您将多个Comparator 组合成一个Comparator

    所以基本逻辑是:

    BeanComparator city = new BeanComparator(Person.class, "getCity");
    BeanComparator age = new BeanComparator(Person.class, "getAge");
    GroupComparator gc = new GroupComparator(city, age);
    Collections.sort(arrayList, gc);
    

    【讨论】:

    • BeanComparatorGroupComparator 是两个外部类,它们依靠反射来完成它们的工作。谈论过度工程......
    • @akappa,只有 BeanComparator 依赖反射。这两个类的重点是查看可重用代码的解决方案。您可以利用这些类,而不是为每个属性或属性组合创建比较器。如果您需要让用户确定任何属性的排序顺序,这是一个有用的解决方案。 Thje BeanComparator 展示了如何创建一个简单的 Comparator,如果您不想使用反射,则可以与 GroupComparator 一起使用,因为链接中给出的原因。
    • 引入一个新的抽象有一些成本——在性能和可读性方面——必须被你抽象出来的工作量以及你能更好地传达你的意图所抵消。在这种情况下,我会说节省是边际的,成本是巨大的。此外,如果我需要例如怎么办?按长度而不是按字典顺序对字符串进行排序?此抽象不支持这一点。或者如果我想以相反的顺序排序怎么办?我必须研究你的界面。相反,如果你使用 lambda 函数作为比较器,你得到的是能立即传达其目的的简洁代码。
    • @akappa,性能是的(我在链接中注意到了这一点)。可读性没有,因为 3 行代码简单直接。您不需要知道类的详细信息就可以使用它,只需要知道 API,您对 JDK 中的任何类都执行此操作。该类确实支持逆序排序,但是我从未暗示您将永远不必再编写自定义 Comparator 。我只是说这些类可以在正确的情况下防止代码膨胀。编程的重点是创建可重用的代码。
    • 和@camickr 放下了麦克风
    【解决方案3】:

    您有两个选项,它们本质上是等效的:

    • 使用stable sort algorithm 执行两种排序:首先按年龄,然后按城市。稳定排序算法是保持两个元素AB的相对顺序的排序算法,如果它们在当前&lt;函数下是等价的。这样,如果你先按年龄排序,当你再次按城市排序并且两个元素具有相同的城市时,它们的相对顺序将由输入顺序决定,因此它们将按年龄排序。
    • 使用比较函数执行单次排序,当A.city != B.city &amp;&amp; A.city &lt; B.cityA.city = B.city &amp;&amp; A.age &gt; B.age 时显示A &lt; B

    请注意,Java 的 Collections.sort 保证是稳定的,因此请选择更适合您需求的策略。

    【讨论】:

      猜你喜欢
      • 2016-04-15
      • 1970-01-01
      • 2013-11-07
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 2023-03-22
      • 2020-12-28
      • 2012-01-02
      相关资源
      最近更新 更多