java - 如何根据映射中键的某些属性对映射进行排序?

标签 java sorting dictionary

假设我们有一个名为 Activity 的类:

public class Activity {
    private Project project;
}

所以每个 Activity 对象都会有一个项目..而且每个项目都有一个单元。两个不同的项目可以具有相同的单位:

public class Project {
    private String projectName; 
    private Unit unit;
}

一个单位也有一个名称:

public class Unit {
    private String unitName;
}

所以目前我有一个像这样的 TreeMap:

SortedMap<Project,List<Activity> myMap

一个例子可能是:

projectOne -> [activityOne,activityTwo,activityThree]
projectTwo -> [activityThree,activityFouractivityFive]
projectThree -> [activityFour,activityFive,activitySix]

等等...

现在假设projectOne 与projectThree 具有相同的单位(unitAAA),projectTwo 具有unitZZZ...

我想按项目元素的单位按字母顺序对 map 进行排序:

projectOne -> [...]
projectThree -> [...] 
projectTwo -> [...]

我怎样才能实现这个目标?我知道 Stackoverflow 中的问题是到目前为止你尝试过什么?,好吧,我真的陷入了这一点,所以除了尝试想出我可以尝试的东西之外,我还没有真正尝试过任何东西。

最佳答案

map 基本上是一个未排序的集合,但也有排序的 map ,例如树形图。在这种情况下,提供一个比较器,根据构造函数对项目进行排序:

SortedMap<Project, List<Activity>> myMap = new TreeMap<>( new Comparator<Project>() {
  public int compare( Project lhs, Project rhs) {

    int r = lhs.unit.unitName.compareTo(rhs.unit.unitName); //note that null checks etc. are omitted for simplicity, don't forget them in your code unless you know for sure that unit and unitName can't be null   
    if( r == 0 && !lhs.equals(rhs)) {
      //take other properties into account for consistent behavior with equals()
      //see "Update 2" below
    }
    return r;
  }
});

请注意,如果您需要使用不同的比较器对 map 进行排序(或无法提供比较器),则必须使用 map 的条目创建一个列表并对其进行排序。

类似这样的事情:

 List<Map.Entry<Project, List<Activity>> l = new ArrayList<>(myMap.entrySet());
 Collections.sort(l, new Comparator<Map.Entry<Project, List<Activity>>() {
   public int compare( Map.Entry<Project, List<Activity> lhs, Map.Entry<Project, List<Activity> rhs) {
    return lhs.getKey().unit.unitName.compareTo(rhs.getKey().unit.unitName);
  }
 });

另请注意,集合或排序映射不可能具有不同的排序顺序,即您只能为元素提供一个比较器或自然排序。

在任何情况下,您都必须更改集合的排序顺序(例如,通过使用Collections.sort(...),或者,如果您需要同时维护多个顺序,请使用多个集合(可以将 View 排序到基本集合/ map )。

更新我将添加一个 TreeMap 副本的示例:

//new TreeMap like above
SortedMap<Project, List<Activity>> copy = new TreeMap<>( new Comparator<Project>() { ... } );
copy.putAll( myMap );

更新2

对于比较器,请注意,它需要与 equals 一致,即如果两个对象相等,则比较器只能返回 0。因此,如果单位相等,您需要考虑 Project 的其他属性。如果没有这个,如果两个项目使用相同的单元,TreeMap 会认为它们是相等的,因此条目可能会丢失。

有关更多信息,请参阅:What does comparison being consistent with equals mean ? What can possibly happen if my class doesn't follow this principle?

如果项目名称是唯一的,则比较方法可能如下所示:

public int compare( Project lhs, Project rhs) {
  //as above null checks etc. are omitted for simplicity's sake
  int r = lhs.unit.unitName.compareTo(rhs.unit.unitName);
  if( r == 0 && !lhs.equals(rhs)) {
    r = lhs.projectName.compareTo( rhs.projectName );

    //you could also use the natural ordering of the projects here:
    //r = lhs.compareTo( rhs );
  }
  return r;
}

关于java - 如何根据映射中键的某些属性对映射进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22171082/

相关文章:

java - 通过 JSON 和 PHP 发送电子邮件后出现 NullpointerException

java - 将 Java ME 移植到 Android(处理文件)

java - aapt.exe 问题

java - 通过旋转 2x2 子网格对 3x3 网格进行排序

SQLite 查询使用 TEMP B-TREE FOR ORDER BY 而不是索引

c++ - 如何以稳定的方式进行部分排序

c++ - 在 TLS 中存储映射 - C++ 中的线程安全

dictionary - 从 Google 街景中提取深度图

java - 应用访问者模式来检测图中的循环

python - 从python中的字典列表中删除字典