当前位置: 首页 > 知识库问答 >
问题:

如何根据地图中键的某些属性对地图进行排序?

胡越泽
2023-03-14

假设我们有一个叫做活动的班级:

public class Activity {
    private Project project;
}

因此,每个活动对象都将有一个项目。。而且每个项目都有一个单元。两个不同的项目可以具有相同的单元:

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

一个单位也有一个名字:

public class Unit {
    private String unitName;
}

所以目前我有一个树状图像这样:

SortedMap<Project,List<Activity> myMap

一个例子可能是:

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

现在让我们假设projectOne与projectThree具有相同的单元(unitAAA),projectThree具有UNITZZ。。。

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

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

我怎样才能做到这一点?我知道问题是到目前为止你试过什么?,我真的被困在这一点上了,所以除了尝试想出我甚至可以尝试的东西外,我还没有真正尝试过任何东西。。

共有2个答案

空鸿云
2023-03-14

无法对HashMap进行排序,但是如果您想显示已排序的映射的内容,可以按单位对项目列表进行排序(在Project上查找Comparator),并从映射中获取相应项目的值。

何章横
2023-03-14

地图基本上是未排序的集合,但也有已排序的地图,例如TreeMap。在这种情况下,提供一个比较器,该比较器根据项目与构造函数之间的关系对项目进行排序:

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

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

像这样的东西:

 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(...),或者,如果您需要同时维护多个顺序,则使用多个集合(可以将视图排序为基地集合/地图)。

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

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

更新2

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

有关更多信息,请参见:比较与相等一致意味着什么?如果我们班不遵循这个原则,会发生什么?

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

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;
}
 类似资料:
  • 问题内容: Stream >> sorted = index.entrySet().stream() .sorted(Map.Entry.comparingByValue()); 类型中的方法不适用于参数 我想根据作为的值的列表对a进行排序。如何使用Java 8中的Stream库实现此目的? 问题答案: 这可能对您有帮助。 我将结果映射的类型更改为 LinkedHashMap 以遵守插入顺序。

  • 问题内容: 我有一个这样的: 我想根据列表值的大小按升序对地图进行排序。我怎样才能做到这一点? 在这种情况下,我希望订购加拿大,印度,美国的钥匙。 问题答案: 没有可保证的迭代顺序,因此您需要收集到一个才能使排序有意义。 之所以引发,是因为合并器功能仅用于并行流],而我们并未使用。 如果您觉得可读性更好,也可以使用:

  • 如何根据条目列表的值和键对地图进行排序 首先按Value desc排序,然后如果值冲突按Key Desc排序 给定地图中的示例: 预期订单:

  • 免责声明:我已经发布过这样一个问题,它被标记为重复。请帮帮我。我已经看过了stackoverflow之前的所有方法,但都没有任何帮助。在我的例子中,提到的所有对Map(Key,Values)进行排序的方法都不起作用,因为我还有一个步骤,即检索值的属性。这一次,我试着详细讲述。 我有一个地图(字符串,对象)在Java,我想排序它使用对象的属性之一。 假设我有一堂课 现在,我创建了一张地图 我想通过类

  • 问题内容: 在主题函数返回的代码中迭代返回的映射时,键未按顺序显示。 我如何才能使键按顺序排列/对地图进行排序,以使键按顺序排列并且值对应? 这是代码。 问题答案: 在围棋博客:去映射在行动中有极好的说明。 当使用范围循环在地图上进行迭代时,未指定迭代顺序,并且不能保证每次迭代之间都相同。从Go 1开始,运行时间会随机化映射迭代顺序,因为程序员依赖于先前实现的稳定迭代顺序。如果需要稳定的迭代顺序,