Java 集合,如 c# KeyedCollection<TKey,TItem>

标签 java c# collections

是否存在与 C# 抽象 KeyedCollection 类具有相同行为的 Java 集合(即可以通过键和索引检索项目)?我环顾四周,但找不到类似的东西。

谢谢, 尼克

最佳答案

这是使用“KeyedItem”接口(interface)的完整实现。我已尽我所能添加评论。

/** 
*  An interface that must be implemented by an item inserted into a KeyedItemHashMap.
*/
public interface KeyedItem {
    /** 
    *  Returns an ID for this item to be used in a KeyedItemHashMap.
    *  @return An ID for this item to be used in a KeyedItemHashMap.
    */
    public String getId();
}

然后是HashMap类的实现...

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Hash table based implementation of the {@code Map} interface.  This
 * implementation provides all of the optional map operations, and permits
 * {@code null} values and the {@code null} key.  (The {@code HashMap}
 * class is roughly equivalent to {@code Hashtable}, except that it is
 * unsynchronized and permits nulls.)  This class makes no guarantees as to
 * the order of the map; in particular, it does not guarantee that the order
 * will remain constant over time.
 *
 * Unlike a typical hash map, this implementation uses KeyedItem's as the 
 * value. A KeyedItem must implement the {@code KeyedItem} interface and 
 * provide a unique ID to avoid collisions within the map.
 * 
 * For more details see the {@code HashMap} class.
 */
public final class KeyedItemHashMap implements Map<String,KeyedItem>{
    private HashMap<String,KeyedItem> m_map;

    /**
     * Constructs an empty HashMap with the default initial capacity (16) and 
     * the default load factor (0.75).
     */
    public KeyedItemHashMap() {
        m_map = new HashMap<>();
    }

    /**
     * Returns the number of key-value mappings in this map.
     * @return The number of key-value mappings in this map.
     */
    public int size() {
        return m_map.size();
    }

    /**
     * Returns {@code true} if this map contains no key-value mappings.
     * @return {@code true} if this map contains no key-value mappings.
     */
    public boolean isEmpty() {
        return m_map.isEmpty();
    }

    /**
     * Returns {@code true} if this map contains a mapping for the specified key.
     * @param key The key whose presence in this map is to be tested.
     * @return {@code true} if this map contains a mapping for the specified key.
     */
    public boolean containsKey(Object key) {
        return m_map.containsKey(key);
    }

    public boolean containsValue(Object keyedItem) {
        return m_map.containsValue(keyedItem);
    }

    /**
     * Returns the string representation of the {@code Object} argument.
     *
     * @param   obj   an {@code Object}.
     * @return  if the argument is {@code null}, then a string equal to
     *          {@code "null"}; otherwise, the value of
     *          {@code obj.toString()} is returned.
     * @see     java.lang.Object#toString()
     */
    public KeyedItem get(Object obj) {
        return m_map.get(String.valueOf(obj));
    }

    /**
     * Associates the specified value with the keyedItem's ID in this map.
     * If the map previously contained a mapping for the keyedItem's ID, the old
     * value is replaced.
     *
     * @param key UNUSED here but necessary for override.
     * @param keyedItem Value that implements the KeyedItem interface. The getId() function will
     * be used to determine the key for the map.
     * @return the previous value associated with {@code keyedItem.getId()}, or
     *         {@code null} if there was no mapping for {@code keyedItem.getId()}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code keyedItem.getId()}.)
     */
    public KeyedItem put(String key, KeyedItem keyedItem) {
        return m_map.put(keyedItem.getId(), keyedItem);
    }

    /**
     * Associates the specified value with the keyedItem's ID in this map.
     * If the map previously contained a mapping for the keyedItem's ID, the old
     * value is replaced.
     *
     * @param keyedItem Value that implements the KeyedItem interface. The getId() function will
     * be used to determine the key for the map.
     * @return the previous value associated with {@code keyedItem.getId()}, or
     *         {@code null} if there was no mapping for {@code keyedItem.getId()}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code keyedItem.getId()}.)
     */
    public KeyedItem put(KeyedItem keyedItem) {
        return m_map.put(keyedItem.getId(), keyedItem);
    }

    /**
     * Removes the mapping for the specified keyedItem's ID from this map if present.
     *
     * @param  keyedItem KeyedItem whose mapping is to be removed from the map.
     * @return the previous value associated with {@code keyedItem.getId()}, or
     *         {@code null} if there was no mapping for {@code keyedItem.getId()}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code keyedItem.getId()}.)
     * @throws ClassCastException if the keyedItem does not implement the KeyedItem interface.
     */
    public KeyedItem remove(Object keyedItem) {
        return m_map.remove(((KeyedItem)keyedItem).getId());
    }

    /**
     * Copies all of the mappings from the specified map to this map.
     * These mappings will replace any mappings that this map had for
     * any of the keys currently in the specified map.
     *
     * @param map mappings to be stored in this map
     * @throws NullPointerException if the specified map is null
     */
    public void putAll(Map<? extends String, ? extends KeyedItem> map) {
        m_map.putAll(map);
    }

    /**
     * Removes all of the mappings from this map.
     * The map will be empty after this call returns.
     */
    public void clear() {
        m_map.clear();
    }

    /**
     * Returns a {@link Set} view of the keys contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own {@code remove} operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * {@code Iterator.remove}, {@code Set.remove},
     * {@code removeAll}, {@code retainAll}, and {@code clear}
     * operations.  It does not support the {@code add} or {@code addAll}
     * operations.
     *
     * @return a set view of the keys contained in this map
     */
    public Set<String> keySet() {
        return m_map.keySet();
    }

    /**
     * Returns a {@link Collection} view of the values contained in this map.
     * The collection is backed by the map, so changes to the map are
     * reflected in the collection, and vice-versa.  If the map is
     * modified while an iteration over the collection is in progress
     * (except through the iterator's own {@code remove} operation),
     * the results of the iteration are undefined.  The collection
     * supports element removal, which removes the corresponding
     * mapping from the map, via the {@code Iterator.remove},
     * {@code Collection.remove}, {@code removeAll},
     * {@code retainAll} and {@code clear} operations.  It does not
     * support the {@code add} or {@code addAll} operations.
     *
     * @return a view of the values contained in this map
     */
    public Collection<KeyedItem> values() {
        return m_map.values();
    }

    /**
     * Returns a {@link Set} view of the mappings contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own {@code remove} operation, or through the
     * {@code setValue} operation on a map entry returned by the
     * iterator) the results of the iteration are undefined.  The set
     * supports element removal, which removes the corresponding
     * mapping from the map, via the {@code Iterator.remove},
     * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
     * {@code clear} operations.  It does not support the
     * {@code add} or {@code addAll} operations.
     *
     * @return a set view of the mappings contained in this map
     */
    public Set<Entry<String, KeyedItem>> entrySet() {
        return m_map.entrySet();
    }
}

这应该足够灵活,您只需将接口(interface)添加到您想要存储的任何类即可。

您想要实现映射接口(interface),以便您的新 HashMap 可以用于通用 HashMap 可以使用的任何功能,不幸的是,这意味着您有一个 put 函数,它接受未使用的键。我已经在评论中指出了这一点。

编辑:修复了一些语法错误并包含导入

关于Java 集合,如 c# KeyedCollection<TKey,TItem>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31914380/

相关文章:

java - 如何使用 .NET 或 JAVA 创建具有数据类型的 XML 文档

c# - 读取 JavaScript 文件并通过 HttpHandler 将其输出回来

c# - 使用泛型类型参数向上转型

java - 如何在Java中按值嵌套值(ArrayList)对Map进行排序?

javascript - 解析之前更改 Meteor.Collection

java - 当扩展 ListView 的 Activity 为 'Launched' 时应用程序崩溃

java - 从存储过程调用流式传输 blob 数据

java - ObjectMapper 截断 Map 中的日期

c# - 与用于键入密码的文本框相关的问题

java - 如何将 NavigableMap 功能与 Guava 的 Multimap(使用 asMap())一起使用?