簡體   English   中英

為什么 EnumMap 不是 Java 中的 SortedMap?

[英]Why is EnumMap not a SortedMap in Java?

Java 中的EnumMap<K extends Enum<K>, V>是按照關聯枚舉的定義明確排序的,您還可以在 javadoc 中看到:

枚舉映射以其鍵的自然順序(聲明枚舉常量的順序)維護。 這反映在集合視圖( keySet()entrySet()values() )返回的迭代器中。

我需要的是使用枚舉作為鍵類型的SortedMap 我想使用headMap()firstKey() ,但我想從EnumMap增加的 cpu+memory 性能中獲利。 TreeMap在這里聽起來像是太多的開銷。

問題:這是否只是在實現中遺漏了,是懶惰(源自AbstractMap )還是有充分的理由說明EnumMap不是SortedMap

打開功能請求

我能夠為OpenJDK找到這個問題 它是從 2005 年開始的,但仍然開放/未解決。

我認為沒有任何“很好的理由”沒有實現這一點。

這不會回答您的主要問題(因為只有原始設計師有答案),但我正在考慮的一種方法是讓您自己實施。 在嘗試基於EnumMap進行SortedMap實現時,我想出了以下類。

這肯定是一個快速而骯臟的實現(並注意它不完全符合SortedMap - 因為沒有滿足視圖要求),但是如果您需要一個,您可以改進它:

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}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM