Java 是否有任何数据结构可以避免重复、保持顺序和随机访问
之前,我正在寻找具有以下特征的数据结构Java 是否有任何数据结构可以避免重复、保持顺序和随机访问,java,python,collections,Java,Python,Collections,之前,我正在寻找具有以下特征的数据结构 避免重复 迭代顺序将与插入顺序相同 在Java中,我使用,在Python中,我使用 现在,在2个要求的顶部,我想有一个额外的要求 能够通过索引进行随机访问,意味着我可以通过数据[123] 是否有可用的数据结构?或者我需要退回使用列表列表能够完全满足第二和第三项要求,但不能满足第一项要求。我可能需要在插入过程中执行手动(和慢速检查)以避免重复?java.util.Set不提供get()和Set()等随机访问方法,因此它的大多数/所有实现也不提供。您可
- 避免重复
- 迭代顺序将与插入顺序相同
- 能够通过索引进行随机访问,意味着我可以通过
数据[123]
是否有可用的数据结构?或者我需要退回使用
列表
<代码>列表能够完全满足第二和第三项要求,但不能满足第一项要求。我可能需要在插入过程中执行手动(和慢速检查)以避免重复?java.util.Set不提供get()和Set()等随机访问方法,因此它的大多数/所有实现也不提供。您可以创建自己的Set
实现来提供此功能,也许可以使用一个ArrayList来保存数据。java.util.Set
不提供get()和Set()等随机访问方法,因此它的大多数/所有实现也不提供。您可以创建自己的Set
实现,该实现将提供此功能,可能带有用于保存数据的ArrayList。LinkedHashSet类提供toArray方法,该方法应适合您的需要。LinkedHashSet类提供toArray方法,这应该适合您的需要。Java中的一个简单方法是创建一个包装类,该类实现了集合
和列表
接口,并且包含哈希集
和数组列表
。更新操作将需要更新两个内部集合,而读取操作将映射到提供正确语义和最佳性能的内部集合。唯一稍微棘手的方法是iterator()
,您需要安排remove
更新这两个集合
这种方法将为读取操作提供“两全其美”的性能,但更新速度必然较慢。特别是,在给定位置插入和移除将执行O(N)
操作
(我要指出的是,LinkedHashSet不是一个直接的解决方案,因为它不提供get(int)
方法。您可以通过LinkedHashSet迭代器实现此方法,从而使其成为O(N)
操作。可能不是您想要的。)
跟进
我还没有找到一个通用的实现类来实现Set
和List
接口。我认为,原因是当您组合接口时,存在语义异常。例如,(正如@ColinD所指出的)如果使用列表中已经存在的元素调用E set(int,E)
,则不清楚结果应该是什么。以一种让每个人都满意的方式来处理这个问题可能是不可能的,我可以理解为什么他们可能决定不去柏油坑游泳
但是,如果您正在为应用程序的内部使用创建一个Set
+List
类,我不认为这是一个主要问题。你也是
- 选择适合您的应用程序的语义
- 将应用程序编码为完全不使用该方法,或者
- 为应用程序编写代码以避免被异常所困扰
set
方法的结果,如果存在重复,则抛出未检查的异常,或者如果存在重复,则返回null
或某个可分辨对象。)
作为记录,自定义集合类违反接口约定并不是不可原谅的。事实上,甚至Java设计人员也会这样做——请参见IdentityHashMap。不可原谅的是,没有在javadocs中记录违反合同的行为。Java中的一个简单方法是创建一个包装类,该类实现
集
和列表
接口,并包含哈希集
和数组列表
。更新操作将需要更新两个内部集合,而读取操作将映射到提供正确语义和最佳性能的内部集合。唯一稍微棘手的方法是iterator()
,您需要安排remove
更新这两个集合
这种方法将为读取操作提供“两全其美”的性能,但更新速度必然较慢。特别是,在给定位置插入和移除将执行O(N)
操作
(我要指出的是,LinkedHashSet不是一个直接的解决方案,因为它不提供get(int)
方法。您可以通过LinkedHashSet迭代器实现此方法,从而使其成为O(N)
操作。可能不是您想要的。)
跟进
我还没有找到一个通用的实现类来实现Set
和List
接口。我认为,原因是当您组合接口时,存在语义异常。例如,(正如@ColinD所指出的)如果使用列表中已经存在的元素调用E set(int,E)
,则不清楚结果应该是什么。以一种让每个人都满意的方式来处理这个问题可能是不可能的,我可以理解为什么他们可能决定不去柏油坑游泳
但是,如果您正在为应用程序的内部使用创建一个Set
+List
类,我不认为这是一个主要问题。你也是
- 选择适合您的应用程序的语义
- 将应用程序编码为完全不使用该方法,或者
- 为应用程序编写代码以避免被异常所困扰
class IndexableUniqueList(object):
"""
>>> a = IndexableUniqueList()
>>> a['x'] = 1
>>> a['x']
1
>>> a['y'] = 2
>>> a['y']
2
>>> a.get_key_by_index(0)
'x'
>>> a.get_value_by_index(0)
1
>>> a.get_key_by_index(1)
'y'
>>> a.get_value_by_index(1)
2
>>> a['x'] = 3
>>> a.get_key_by_index(0)
'x'
>>> a.get_value_by_index(0)
3
>>> a.set_value_by_index(0, 4)
>>> a['x']
4
>>> [val for val in a]
['x', 'y']
"""
def __init__(self):
self.items_by_index = []
self.items_by_key = {}
def __getitem__(self, key):
return self.items_by_key[key][1]
def __setitem__(self, key, value):
if key in self.items_by_key:
idx, old_value = self.items_by_key[key]
self.items_by_key[key] = (idx, value)
self.items_by_index[idx] = (key, value)
return
idx = len(self.items_by_index)
self.items_by_key[key] = (idx, value)
self.items_by_index.append((key, value))
def get_key_by_index(self, idx):
return self.items_by_index[idx][0]
def get_value_by_index(self, idx):
key = self.get_key_by_index(idx)
return self.items_by_key[key][1]
def set_value_by_index(self, idx, value):
key = self.items_by_index[idx][0]
self[key] = value
def __iter__(self):
for key, value in self.items_by_index:
yield key