假设我想存储学生参加的每个班级的记录。学生和班级都有唯一的标识符,但是多个学生可以参加同一个班级,学生可以参加多个班级。
我想以这样的方式安排这些记录,即我不必搜索复杂度为O(n)的所有记录,但是所有具有相同类ID的对象都在同一个槽中解析,就像哈希表一样工作,除了我发现java HashSet 不支持重复。
所以接下来我的问题是...我想返回所有那些哈希码已解析到表中相同位置的记录的集合,但该数据结构必须支持重复的课程,因为多个学生可以上课X。一个这样的插槽将是解析到相同插槽的所有记录的列表。
答案 0 :(得分:4)
首先解决哈希码的一般问题。
如果您有许多映射到相同哈希码的不同键,则一般工作中的哈希表仍然有效。但是,哈希表是1对1映射。它们将每个不同的键映射到一个(并且只有)记录/条目。在Java上下文中,这适用于所有Map
集合,也适用于所有Set
集合......将集合建模为简并形式的映射。
如果您希望一个键映射到(可能)多个不同的记录/值,那么您需要一个多映射数据结构。这可以模拟(使用Java集合类型)为Map<K, List<V>>
或Map<K, Set<V>>
。
总结:
重要的是密钥的独特性,而不是哈希码的独特性。 (哈希表可以处理哈希码冲突。)
如果你有非独特的键,那么你需要一张多地图。
查看您的特定用例,您看到的是一组具有两个外部密钥的出勤记录;即类ID和源ID。 (我假设每个出勤记录都包含一些代表学生上课的数据。)
这里有两个密钥的事实意味着您希望在应用程序的不同位置进行查询;例如“查找学生X的出勤记录”,“查找Y班的所有出勤记录”。
这意味着您实际上需要2个多地图来支持这些查询;例如Map<StudentID, <Set<AttendanceRecord>>
和Map<CourseID, <Set<AttendanceRecord>>
。
您需要维护几个不变量。这些集合(当然)只包含与各自学生或课程相关的AttendanceRecord
个对象。