java - 为什么 EnumMap 不是 Java 中的 SortedMap?

标签 java collections enums sortedmap enum-map

EnumMap<K extends Enum<K>, V>在 Java 中,按照相关枚举的定义明确排序,正如您在 javadoc 中看到的:

枚举映射以其键的自然顺序(声明枚举常量的顺序)维护。这反射(reflect)在集合 View ( keySet()entrySet()values() )返回的迭代器中。

我需要的是一个 SortedMap使用枚举作为键类型。我想使用像 headMap() 这样的方法或 firstKey() ,但我想从 EnumMap 增加的 cpu+内存性能中获利s。一个 TreeMap听起来这里的开销太大了。

问题:这是在实现中遗漏的,是懒惰(源自 AbstractMap )还是有充分的理由为什么 EnumMap不是 SortedMap ?

最佳答案

这不会回答您的主要问题(因为只有原始设计师有答案),但我正在考虑的一种方法是让您自己实现。在尝试制作 SortedMap 时基于 EnumMap 的实现,我想出了以下类(class)。

这肯定是一个快速而肮脏的实现(请注意,它不完全符合 SortedMap - 因为未满足 View 要求),但是如果您需要,可以改进它:

class SortedEnumMap<K extends Enum<K>, V> 
    extends EnumMap<K, V> 
    implements SortedMap<K, V> {

    private Class<K> enumClass;
    private K[] values;

    public SortedEnumMap(Class<K> keyType) {
        super(keyType);
        this.values = keyType.getEnumConstants();
        this.enumClass = keyType;

        if (this.values.length == 0) {
            throw new IllegalArgumentException("Empty values");
        }
    }

    @Override
    public Comparator<? super K> comparator() {
        return Comparator.comparingInt(K::ordinal);
    }

    @Override
    public SortedMap<K, V> subMap(K fromKey, K toKey) {
        List<K> keys = Arrays.stream(this.values)
                .dropWhile(k -> k.ordinal() < fromKey.ordinal())
                .takeWhile(k -> k.ordinal() < toKey.ordinal())
                .collect(Collectors.toList());

        return this.forKeys(keys);
    }

    @Override
    public SortedMap<K, V> headMap(K toKey) {
        List<K> keys = new ArrayList<>();

        for (K k : this.values) {
            if (k.ordinal() < toKey.ordinal()) {
                keys.add(k);
            } else {
                break;
            }
        }

        return this.forKeys(keys);
    }

    @Override
    public SortedMap<K, V> tailMap(K fromKey) {
        List<K> keys = new ArrayList<>();

        for (K k : this.values) {
            if (k.ordinal() >= fromKey.ordinal()) {
                keys.add(k);
            }
        }

        return this.forKeys(keys);
    }

    //Returned map is NOT a "view" or the current one
    private SortedEnumMap<K, V> forKeys(List<K> keys) {
        SortedEnumMap<K, V> n = new SortedEnumMap<>(this.enumClass);
        keys.forEach(key -> n.put(key, super.get(key)));

        return n;
    }

    @Override
    public K firstKey() {
        return this.values[0];
    }

    @Override
    public K lastKey() {
        return this.values[this.values.length - 1];
    }
}

并进行快速测试(尚未发现错误):
SortedMap<Month, Integer> m = new SortedEnumMap(Month.class);

for (Month v : Month.values()) {
    m.put(v, v.getValue());
}

System.out.println("firstKey():       " + m.firstKey());
System.out.println("lastKey():        " + m.lastKey());
System.out.println("headMap/June:     " + m.headMap(Month.JUNE));
System.out.println("tailMap/June:     " + m.tailMap(Month.JUNE));
System.out.println("subMap/April-July " + m.subMap(Month.APRIL, Month.JULY));

我得到:
firstKey():       JANUARY
lastKey():        DECEMBER
headMap/June:     {JANUARY=1, FEBRUARY=2, MARCH=3, APRIL=4, MAY=5}
tailMap/June:     {JUNE=6, JULY=7, AUGUST=8, SEPTEMBER=9, OCTOBER=10, NOVEMBER=11, DECEMBER=12}
subMap/April-July {APRIL=4, MAY=5, JUNE=6}

关于java - 为什么 EnumMap 不是 Java 中的 SortedMap?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59749754/

相关文章:

java - 在Kibana中不可见的字段

java集合框架-读取输入和输出行floor(n/2),...,n-1

java - 从 HashMap 获取值并填充 Java 对象

java - "A List is an ordered Collection..."是什么意思?

enums - 比较 Rust 中的嵌套枚举变体

java - 获取 HashMap 中值的大小/长度

java - XSD 到 HTML 表单

java - 如何解决两个接口(interface)中方法名称冲突

c# - 使属性只能通过特定方法设置

c++ - 从不兼容类型 'int' 分配给 [custom typdef]