Java 是否有类似ListHashMap的数据结构?
我一直在努力寻找一种数据结构,它将:Java 是否有类似ListHashMap的数据结构?,java,data-structures,Java,Data Structures,我一直在努力寻找一种数据结构,它将: 让我检查O(1)时间(哈希集)中的重复项 保留插入顺序,以及 请允许我获取该有序列表的子集 我找到的最接近的东西是LinkedHashSet,但它没有实现List接口,允许我调用List函数(比如subList)。我找不到这样的结构有什么原因吗?我即将实现我自己版本的LinkedHashSet,但改用ArrayList(与LinkedHashSet支持的链接列表相反)。我还从org.antlr.misc库中找到了OrderedHashSet,但由于没有实现所
LinkedHashSet
,但它没有实现List
接口,允许我调用List
函数(比如subList
)。我找不到这样的结构有什么原因吗?我即将实现我自己版本的LinkedHashSet
,但改用ArrayList
(与LinkedHashSet
支持的链接列表相反)。我还从org.antlr.misc
库中找到了OrderedHashSet
,但由于没有实现所需的子列表函数,这也存在不足。。。所以我真的很困惑为什么不需要这个?或者我只是没想到要找一个合适的名字
编辑:我不仅试图找到一个现有的结构来满足这个要求,而且在没有的情况下,我试图找出它为什么不存在。谁能回答这个问题,谁就能得到公认的答案,因为我已经知道如何实现它:)
编辑2:对不起,我应该更清楚我的第一个要求,我真的只需要检查副本真的有效。对我来说太晚了。数据结构不可能同时提供这些东西,它们是相互矛盾的:如果您在O(1)时间内插入和访问元素,这意味着它们是随机分布的(使用哈希代码),如果您想保留顺序,那么插入和访问将花费您更多的时间。 我相信你要找的是一个HashSet,而不是HashMap。这取决于插入的顺序对项目的未来是否至关重要,您可以使用HashSet(快速、随机访问和插入)或ArrayList(较慢,但保持顺序)。 我认为您不太可能创建一个满足您需求的数据结构。会有帮助吗
不完全是O(1)(参考列表要求,第1点),但支持自然排序(第2点)和子集操作(第3点)。基本上,您所发现的是提供O(1)点查找但提供有效范围扫描(迭代)的东西。在数据库区域中,有时会调用这样的东西,其中的数据使用一些查找结构(如或)进行组织,但叶节点或索引项按特定顺序排序(在您的示例中,是按插入顺序排序)。下面显示了聚集B树的示例,其中@Itay Maman的解决方案是聚集散列索引的示例 在Java中,没有这样的类能够满足您的需要,这可能是因为它的复杂性——很难(或几乎不可能)有一个这样的实现对所有工作负载都能起到最好的作用(例如,您多长时间执行一次范围扫描,多长时间执行一次点查找,它是否允许多个读卡器和多个写卡器?…等等),以下是一些可能的解决方案,取决于您的用例
ArrayList.subList()
),因为从ArrayList
返回的(子)列表在创建后不允许数组列表更改其大小。幸运的是,在AbstractList
的帮助下,这非常简单(只需重写两种方法)
p1包;
导入java.util.AbstractList;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.HashSet;
导入java.util.Iterator;
导入java.util.List;
导入java.util.Map;
导入java.util.Set;
公共类有序集{
私有最终列表=新的ArrayList();
私有最终集值=新HashSet();
/**
*如果不是dup,则插入值。
*@如果实际插入了“值”(不是dup),则返回true。
*/
公共布尔put(字符串值){
if(值.包含(值))
返回false;
增加(价值);
列表。添加(值);
返回true;
}
公共布尔包含(字符串)
package p1;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class OrderedSet {
private final List<String> list = new ArrayList<>();
private final Set<String> values = new HashSet<>();
/**
* Inserts a value if it is not a dup.
* @return true if "value" was actually inserted (not a dup).
*/
public boolean put(String value) {
if (values.contains(value))
return false;
values.add(value);
list.add(value);
return true;
}
public boolean contains(String string) {
return values.contains(string);
}
public Iterator<String> iterator() {
return list.iterator();
}
public int size() { return list.size(); }
public List<String> subList(int begin, int end) {
return new MyList(begin, end);
}
private class MyList extends AbstractList<String> {
private final int begin;
private final int end;
public MyList(int begin, int end) {
this.begin = begin;
this.end = end;
}
@Override public String get(int index) {
return list.get(begin + index);
}
@Override public int size() {
return end - begin;
}
}
}
package p1;
import static org.junit.Assert.*;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
public class OrderedSetTest {
@Test
public void test() {
OrderedSet om = new OrderedSet();
assertTrue(om.put("a"));
assertEquals(1, om.size());
assertTrue(om.put("b"));
om.put("c");
assertEquals(3, om.size());
assertFalse(om.put("a"));
assertEquals(3, om.size());
om.put("d");
assertEquals(4, om.size());
om.put("d");
assertEquals(4, om.size());
om.put("e");
assertEquals(5, om.size());
assertTrue(om.contains("a"));
assertTrue(om.contains("b"));
assertTrue(om.contains("c"));
assertTrue(om.contains("d"));
assertTrue(om.contains("e"));
assertFalse(om.contains("a_"));
assertFalse(om.contains("b_"));
assertFalse(om.contains("f"));
Iterator<String> iter = om.iterator();
assertTrue(iter.hasNext());
assertEquals("a", iter.next());
assertTrue(iter.hasNext());
assertEquals("b", iter.next());
assertTrue(iter.hasNext());
assertEquals("c", iter.next());
assertTrue(iter.hasNext());
assertEquals("d", iter.next());
assertTrue(iter.hasNext());
assertEquals("e", iter.next());
assertFalse(iter.hasNext());
List<String> sub = om.subList(2, 4);
assertArrayEquals(new String[] { "c", "d" }, sub.toArray(new String[0]));
}
}