java - 在 TreeMap 的 Key 上对自定义数据结构进行排序

标签 java sorting treemap

我正在尝试根据键对 TreeMap 进行排序。 Key 是一些具有 int、List、String 等的自定义 DataStructure。 我期待排序的成员有一些重复项。假设该成员是 Rank。不止 1 个对象可以具有相同的等级。

简化版示例:

注意:在下面的 CompareTo 方法中,不会有意返回 0 以不忽略重复项。(如果这不是避免重复项的正确方法,请纠正我)

import java.util.TreeMap;


public class TreeTest {

public static void main(String[] args) {
    TreeMap<Custom,String> t = new TreeMap<Custom,String>();
    Custom c1 = new Custom();
    c1.setName("a");
    c1.setRank(0);

    Custom c2 = new Custom();
    c2.setName("b");
    c2.setRank(1);

    Custom c3 = new Custom();
    c3.setName("c");
    c3.setRank(0);

    t.put(c1, "first");
    t.put(c2, "Second");
    t.put(c3, "Third");

    System.out.println(t.keySet());

    for(Custom c:t.keySet()){
        System.out.println(t.get(c));
    }
  }
}

和自定义对象

package com.example.ui;

 public class Custom implements Comparable<Custom>{

int rank;
String name;

public int getRank() {
    return rank;
}

public void setRank(int rank) {
    this.rank = rank;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}



@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    result = prime * result + rank;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Custom other = (Custom) obj;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    if (rank != other.rank)
        return false;
    return true;
}

    // 0 is not returned intentionally to NOT ignore duplicates.
 public int compareTo(Custom o) {
    if(o.rank>this.rank)
        return 1;
    if(o.rank==this.rank)
        return -1;
    return -1;
 }
 }

输出:

[com.example.ui.Custom@fa0, com.example.ui.Custom@fbe, com.example.ui.Custom@f80]
null
null
null

预期: 第一、第二、第三分别基于排名 0、1、0。

我在 Google 上查看了几个示例。它们中的大多数是使用具有原始数据类型的键或值对 TreeMap 进行排序的基本用法,但在对成员进行排序时没有重复项 是自定义键数据结构的一部分。

请帮忙?

最佳答案

问题是你的compareTo实现与equals不一致,这是TreeMap要求的.来自 API 文档:

Note that the ordering maintained by a sorted map (whether or not an explicit comparator is provided) must be consistent with equals if this sorted map is to correctly implement the Map interface.

一个可能的一致实现是首先按等级比较,然后如果等级值相等则按名称比较。对于等级相同且名称相同的两个 Custom 实例,您不应期望能够将它们都存储为同一个 Map 中的键 - 这违反了 Map 的约定

public int compareTo(Custom o) {
  int ret = this.rank - o.rank;

  // Equal rank so fall back to comparing by name.
  if (ret == 0) {
    ret = this.name.compareTo(o.name);
  }

  return ret;
}

关于java - 在 TreeMap 的 Key 上对自定义数据结构进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7385189/

相关文章:

java - 如何在不关闭服务器的情况下清除/删除所有 Weblogic 日志?

ios - 使用 NSSortDescriptor 在 iOS 中对包装对象数组进行排序

python - 如何循环数据帧列以迭代对数据帧进行排序

java - 如何根据 map 键制作一组

r - 是否可以自定义 rpivottable 树形图的大小

java Locale.Builder setExtension(Locale.UNICODE_LOCALE_EXTENSION

java - Spring 集成: Poller acting weird

Java 问题遍历类的树形图集合

java - Intellij 中的故障排除 "UNRESOLVED DEPENDENCIES"

c++ - 快速排序实现,找不到错误