Java 在地图中正确使用存储对象

Java 在地图中正确使用存储对象,java,dictionary,collections,Java,Dictionary,Collections,假设我需要存储一组学生对象,每个学生都有一个唯一的id。一个选项是将所有学生都存储在一个列表中,但在搜索学生时,我必须执行线性搜索并检查他们的id。另一个选项是使用映射,类似于:map,其中键是映射到实际学生对象的学生id 对于给定的问题,这是一种合理的方法吗?一方面,它感觉不错,因为我可以通过学生的id轻松检索学生,然而,另一方面,它感觉我稍微冗余地存储了id,该id已经存在于学生对象中-因此我存储了两次,但关键是查找机制 我的add是这样的: public void add(Student

假设我需要存储一组学生对象,每个学生都有一个唯一的id。一个选项是将所有学生都存储在一个列表中,但在搜索学生时,我必须执行线性搜索并检查他们的id。另一个选项是使用映射,类似于:map,其中键是映射到实际学生对象的学生id

对于给定的问题,这是一种合理的方法吗?一方面,它感觉不错,因为我可以通过学生的id轻松检索学生,然而,另一方面,它感觉我稍微冗余地存储了id,该id已经存在于学生对象中-因此我存储了两次,但关键是查找机制

我的add是这样的:

public void add(Student s) {
     lookup.put(s.getId(), s);
}

希望这种冗余是您在编程中遇到的唯一冗余

在性能和可读性方面,使用具有唯一对象id的映射的附加值值得这种做法产生的少量开销


如果您真的觉得这项开销太大,则可以将放置在地图数据结构中的对象从ID属性中剥离,并且ID属性将仅用作键,然后在检索过程中,您可以从地图键推断ID。

在这种情况下,没有真正正确的用法。你必须考虑你将如何处理这个集合,一旦你完成了它。你要重复它吗?你想把它分类吗

当然,可以创建一个
映射
,自动将键从值中拉出,但是,由于迭代或排序可能变得更加困难,该结构的可用性也受到限制

这里有一个
CurriedHashMap
,它可以满足您的需求。忽略它正在引擎盖下使用
HashMap
功能这一事实

class CurriedHashMap<K, V> extends HashMap<K, V> {

    /**
     * Function that extracts key from value.
     */
    final Function<V, K> curry;

    public CurriedHashMap(Function<V, K> curry) {
        this.curry = curry;
    }

    /**
     * One-value put - the key is intuited from the value using the `curry` function.
     */
    public V put(V value) {
        return super.put(curry.apply(value), value);
    }

}
类CurriedHashMap扩展了HashMap{
/**
*从值中提取键的函数。
*/
最后功能咖喱;
公共货币地图(功能货币){
this.curry=咖喱;
}
/**
*一个值put-使用'curry'函数从值中插入键。
*/
公共V值(V值){
返回super.put(curry.apply(value),value);
}
}

我就是这么做的。您还可以在student objectdata结构上实现equals()和hashCode方法。数据结构与感觉无关