我正在寻找能够满足这两个要求的某种设置数据结构:
这是我到目前为止所得到的,但我真的希望有一个现有的,不那么尴尬的数据结构。
/**
* This MUST support both
* (1) Looking up by A - O(n)
* (2) Iteration by sorted Foo<A, B>
*/
public class MySet<Foo<A, B>> extends TreeSet<Foo<A, B>>
{
private Map<A, Foo<A, B>> temp = new HashMap<A, Foo<A, B>>();
public Foo<A, B> getNode(A a)
{
return temp.get(a);
}
@Override
public boolean add(Foo<A, B> foo)
{
temp.put(foo.getA(), foo);
return super.add(foo);
}
}
我的Foo
课程如下:
public class Foo<A, B>
{
private A a; //Can NEVER be null
private B b; //Can NEVER be null
//... constructor and stuff omitted
public int compareTo(Foo<A, B> that)
{
if (this.equals(that))
return 0;
//Compare by a first
int ret = this.a.compareTo(that);
if (ret == 0)
return 0;
//Compare by b
return this.b.compareTo(that.b);
}
public boolean equals(Object obj)
{
if (!(obj instanceof Foo))
return false;
Foo rhs = (Foo) obj;
return this.a.equals(rhs.a) && this.b.equals(rhs.b);
}
}
更新
以下是我的设置的用例:
MySet<Foo<SomeA, SomeB>> mySet = getTheData(); //getTheData() returns a set with a bunch of Foo objects
SomeA a = getA(); //getA() returns some instance of SomeA that I'm interested in
我希望能够检查集合并RETRIEVE一个Foo对象(如果存在),以便Foo.getA()== a;
mySet.getNode(a);
答案 0 :(得分:0)
你可以通过使用一些额外的空间来获得它。所以你需要一个HashSet。此外,每个元素都将指向排序顺序中的下一个值。我们假设您有键1,3,5,10,并且您正在使用线性探测。
value array = [3, 5, null, null, 10, 1];
pointer array = [1, 4, null, null, null, 0];
因此值数组包含值。哈希函数决定值的位置。所以在上面的例子中,h(1)= 5(1进入索引5),h(3)= 0,h(5)= 1,h(10)= 4.索引2,3为零(未来元素的开放空间)。指针数组说明哪个元素在排序顺序中跟随当前元素。所以,让我们说我们正在做set.contains(3),它将导致计算h(3)(将产生0),并且我们知道该元素存在于集合中。如果我们想要按照排序顺序在元素集中的下一个元素,我们会查看指针数组中的值。因此对于值3(在值数组中的位置0),我们通过查找指针数组中的索引(pointer_array [0],即1)来获取排序顺序中的下一个元素,然后查找value_array [1],即5。
这是一个非常常见的实现。 Java的LinkedHashMap通常用作LRU缓存,它实现为哈希映射+双向链接密钥列表。双向链表中的键按其访问顺序排列。
在您的情况下,当您插入元素时,您需要调整非常慢的指针数组。你必须进行线性扫描。 如果这不是只读的,您可以使用以下方法。
在您的数据结构中,有一个hashset和一个avl树,一个红黑树或任何其他平衡的二叉树。每当你进行containsKey测试时,它都是 O(1)。无论何时枚举,都可以使用二进制树在线性时间中按排序顺序遍历它们。无论何时插入新元素,还要将其插入二叉树和HashSet中。删除时,从哈希集和二叉树中删除该元素。因此删除和插入变为 O(log n)。
答案 1 :(得分:-2)
我认为您应该尝试在google guava库中使用MultiMaps。 它的使用非常简单:
Map<Salesperson, List<Sale>> map = new Hashmap<SalesPerson, List<Sale>>();
public void makeSale(Salesperson salesPerson, Sale sale) {
List<Sale> sales = map.get(salesPerson);
if (sales == null) {
sales = new ArrayList<Sale>();
map.put(salesPerson, sales);
}
sales.add(sale);
}
可以替换为,
Multimap<Salesperson, Sale> multimap = new ArrayListMultimap<Salesperson,Sale>();
public void makeSale(Salesperson salesPerson, Sale sale) {
multimap.put(salesperson, sale);
}
但是你必须要小心,多图将使用相同的键来保留条目,这与使用最新的等效键替换等效键的hashmaps不同。
Google Guava Libraries具有许多具有不同功能的其他数据结构。您可以在其维基上找到有关它的信息。
希望这有用。