问题描述
谁能帮助我弄清楚,java中是否有任何集合类型(或任何语言激动性的集合类型)为indexOf(Item item)
操作提供O(1)时间复杂度? [您可以假设没有重复项,或者只是第一个要返回的索引]
如果什么都没有,谁能帮我推断出没有形成的原因吗?有什么特殊原因吗?
解决方法
没有具有该属性的Java(标准)集合类型。
indexOf(Object)
方法是在List
中声明的,没有List
实现比O(N)
查找更好。
还有其他集合类型提供O(logN)
或O(1)
查找,但是它们不像indexOf(Object)
那样返回位置(和索引)。 ({HashMap
和HashSet
分别提供get(key)
的{{1}}和contains(object)
。)
如果什么都没有,谁能帮助我推断出没有形成这种现象的原因吗?有什么特殊原因吗?
因为提供了这样功能的数据结构会很复杂,并且(可能)变慢和/或合并O(1)
和ArrayList
的缺点。
我想不出一种好的方法来实现具有快速查找的列表;即没有严重缺陷的产品。如果有一个好的方法,我希望Java团队知道它……并将它包含在Java SE库中。这类似于为什么没有通用的 concurrent 列表类型。
问题是设计通用收集类型涉及折衷。当针对一种访问方式进行优化时,针对另一种访问方式进行了非优化。看来。
,要在O(1)
中的集合中查找元素的索引,您需要能够直接检索元素的索引而无需搜索。 List
或array
不允许我们这样做(需要O(N)
),并且Set
的排序没有 1 。>
我们剩下一个Map
,但Map是一个键值对。
您可以创建一个映射,其中键作为元素,值作为索引,作为集合的辅助数据结构。缺点是您需要在更新集合(列表/数组)时更新地图
或者只是使用地图并删除您的收藏集。
1 indexOf
方法在List
上,而不在Collection
上。
地图似乎是最简单的解决方案,但只是为了好玩:(剩下的List的实现留给读者练习)
package org.example;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class HashList<E> {
private final List<E> list = new ArrayList<>();
private final Map<E,Set<Long>> indexes = new HashMap<>();
public long indexOf(E item) {
Set<Long> indexSet = indexes.get(item);
if (indexSet == null || indexSet.isEmpty()) {
return -1;
} else {
return indexSet.iterator().next();
}
}
public void add(E item) {
list.add(item);
long index = list.size() - 1;
Set<Long> indexSet = indexes.get(item);
if (indexSet == null) {
indexSet = new TreeSet<>();
indexes.put(item,indexSet);
}
indexSet.add(index);
}
public static void main(String... args) {
HashList<String> list = new HashList<>();
assertTrue(list.indexOf("foo") == -1);
list.add("foo");
assertTrue(list.indexOf("foo") == 0);
list.add("bar");
assertTrue(list.indexOf("bar") == 1);
list.add("foo");
// still 0 for the first occurrence
assertTrue(list.indexOf("foo") == 0);
}
private static void assertTrue(boolean truth) {
if (!truth) {
throw new RuntimeException();
}
}
}