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

Kun*_*nal 1 java sorting treemap

我想在key上对TreeMap进行排序.Key是一些具有int,List,String等的自定义DataStructure.我期望排序的成员有一些重复.假设成员是Rank.超过1个对象可以具有相同的排名.

简化版示例:

注意:在CompareTo方法中,0不会故意返回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));
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

和自定义对象

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;
 }
 }
Run Code Online (Sandbox Code Playgroud)

输出::

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

预期:第一,第二,第三,分别基于等级0,1,0.

我在Google上看了几个例子.其中大多数是使用具有原始数据类型的键或值的TreeMap排序的基本用法,但是在排序成员时没有重复项是自定义键DataStructure的一部分.

请帮忙?

Ada*_*ski 7

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

请注意,如果此有序映射要正确实现Map接口,则由有序映射维护的排序(无论是否提供显式比较器)必须与equals一致.

一种可能的一致实现方式是首先按等级进行比较,然后按等级进行比较,如果等级值相等.对于具有相同排名和相同名称的两个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;
}
Run Code Online (Sandbox Code Playgroud)