3

这基本上不是如何HashMap根据键进行排序。为此,我可以TreeMap不眨眼直接使用 :)

我现在拥有的是

Map<String, Object> favoritesMap = new HashMap<String, Object>();
and its contents can be
["Wednesdays" : "abcd"]
["Mondays" : "1234"]
["Not Categorized" : "pqrs"]
["Tuesdays" : "5678"]

我想根据键对 HashMap 进行排序,除此之外,我需要“未分类”作为最后一个检索。

所以在迭代 keySet 时预期的是

["Mondays", "Tuesdays", "Wednesdays", "Not Categorized"] i.e. sorted on keys and "Not Categorized" is the last one

考虑HashMap在创建时进行并在最后添加["Not Categorized" : "pqrs"]HashMap不保证顺序:)

解决方案的任何其他指针?

4

4 回答 4

5

TreeMap您是否出于某些外部原因而专门排除?如果不是,您显然可以使用TreeMap特制的Comparator.

你考虑过其他SortedMap的吗?

如果TreeMap肯定出局,我会扩展HashMap并使它看起来总是有一个条目,但这肯定不是一件微不足道的工作。SortedMap在走这条路之前,您应该有一个很好的理由不使用 a 。

添加

这是一个示例,说明如何使特定条目始终使用 a 排序到末尾TreeMap

// This key should always appear at the end of the list.
public static final String AtEnd = "Always at the end";

// A sample map.
SortedMap<String, String> myMap =
        new TreeMap<>(
        new Comparator<String>() {
          @Override
          public int compare(String o1, String o2) {
            return o1.equals(AtEnd) ? 1 : o2.equals(AtEnd) ? -1 : o1.compareTo(o2);
          }
        });

private void test() {
  myMap.put("Monday", "abc");
  myMap.put("Tuesday", "def");
  myMap.put("Wednesday", "ghi");
  myMap.put(AtEnd, "XYZ");

  System.out.println("myMap: "+myMap);
  // {Monday=abc, Tuesday=def, Wednesday=ghi, Always at the end=XYZ}
}

我想知道你是否正在寻找它的一些变体?

于 2013-01-31T10:28:54.747 回答
3

您可以通过使用来实现这一点,LinkedHashMap因为它保证按插入顺序返回结果。

另请查看以下帖子以了解地图类型之间的差异。

HashMap、LinkedHashMap、TreeMap的区别

或者只是创建一个自定义类,它拥有与值不同的键。根据该类的键进行排序。对于您的情况,使键值与当天相同,对于“未分类”情况,请确保其键启动时间晚于任何其他键,例如将其设置为“Z_Not Categorized”。

public ComplexKey
{
    String key;
    String value;
}

ComplexKey monday = new ComplexKey("monday", "monday");
ComplexKey notCategorized = new ComplexKey("Z_Not Categorized", "Not Categorized");

然后你可以编写一个自定义比较器,根据complexKey类的键对值进行排序。

于 2013-01-31T10:22:16.603 回答
1

在你的情况下,我会使用 TreeMap:

Map<DayOfWeek, Object> favoritesMap = new TreeMap<>();

DayOfWeek你声明的类在哪里:

class DayOfWeek implements Comparable<DayOfWeek> {

因为将几天的 wooks 排序为字符串并不方便。

于 2013-01-31T10:25:48.800 回答
1

事实上,键总是被排序的。如果您将地图输出几次,您会发现结果保持不变。

首先,我将再次八卦散列:

原因是散列。每个对象都有hashCode()方法。散列空间就像一个大数组,其中包含所有可能的散列值作为索引。当一个新元素插入 aHashSet或一个新元素对放入 aHashMap时,根据其哈希码将其放入哈希空间。如果两个元素具有相同的哈希码,则将它们与equals()方法进行比较,如果不相等,则将新元素放在它旁边。

然后,如果您知道那里发生了什么,您可以实现如下代码:

import java.util.*;

class MyString {
    private String str;

    public MyString (String str) {
        this.str = str;
    }

    public String toString () {
        return str;
    }

    public boolean equals (Object obj) {
        if (obj.getClass().equals(MyString.class)) {
            return obj.toString().equals(str);
        }
        return false;
    }

    public int hashCode () {
        if (str.equalsIgnoreCase("Not Categorized")) {
            return Integer.MAX_VALUE;
        } else if (str.hashCode() == Integer.MAX_VALUE) {
            return 0;
        }
        return str.hashCode();
    }
}

public class Test {
    public static void main (String args[]) {
        Map<MyString, String> m = new HashMap<MyString, String>();
        m.put(new MyString("a"), "a");
        m.put(new MyString("c"), "c");
        m.put(new MyString("Not Categorized"), "NC");
        m.put(new MyString("b"), "b");
        Set<MyString> keys = m.keySet();
        for (MyString k : keys) {
            System.out.println(m.get(k));
        }
    }
}

结果是“未分类”总是最后出现。原因很简单:它的哈希值总是整数的最大值。

我创建一个 String 包装类的原因是 String 类是最终的,它不能被扩展。所以通过这种方式,你的类结构会有一点改变,但不会太大。


可以使用 TreeMap,但效率会降低:

public static void main (String args[]) {
    Map<String, String> m = new TreeMap<String, String>(new Comparator<String>() {
        public int compare (String s1, String s2) {
            if (s1.equals(s2)) {
                return 0;
            }
            if (s1.equalsIgnoreCase("Not Categorized")) {
                return 1;
            }
            if (s2.equalsIgnoreCase("Not Categorized")) {
                return -1;
            }
            if (s1.hashCode() > s2.hashCode()) {
                return 1;
            } else if (s1.hashCode() < s2.hashCode()) {
                return -1
            } else {
                return 0;
            }
        }

        public boolean equals (Object obj) {
            return false;
        }
    });
    m.put("a", "a");
    m.put("c", "c");
    m.put("Not Categorized", "NC");
    m.put("b", "b");
    Set<String> keys = m.keySet();
    for (String k : keys) {
        System.out.println(m.get(k));
    }
}

结果是一样的。它会对所有元素进行排序,但不会改变其他字符串的散列顺序,它只会确保“未分类”始终是最大的。

于 2013-01-31T16:51:10.353 回答