[英]complex collection in java
我需要使用以下访问方法定义用户定义对象的集合:
每个对象都有一个主键和一个辅助键(不保证唯一)。 将对象添加到集合时,应将其插入某个位置,以便对辅助键值进行排序。 应使用主键或集合中的位置提取或删除每个对象。
实现此系列的最佳方法是什么? (主键和对象的地图将提供一半的访问权限,排序的列表将提供另一半。如何根据我的要求组合这些?)
您可以轻松地自己编写这样的内容,其中您有一个(普通的) HashMap
,只有主键的值,然后是另一个主键的二级键的PriorityQueue
(看作辅助键并不总是唯一的,所以你不能使用Map
类型)。
这是一个完整的,有效的例子:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class MyCollection<T, TPrimaryKey, TSecondaryKey extends Comparable<TSecondaryKey>> {
private HashMap<TPrimaryKey, T> primaryKeyMap;
private List<PrimarySecondaryKeyPair> primarySecondaryKeyList;
public MyCollection() {
primaryKeyMap = new HashMap<TPrimaryKey, T>();
primarySecondaryKeyList = new ArrayList<PrimarySecondaryKeyPair>();
}
public MyCollection(int initialCapacity) {
primaryKeyMap = new HashMap<TPrimaryKey, T>(initialCapacity);
primarySecondaryKeyList = new ArrayList<PrimarySecondaryKeyPair>(initialCapacity);
}
private class PrimarySecondaryKeyPair implements Comparable<PrimarySecondaryKeyPair> {
public TPrimaryKey primaryKey;
public TSecondaryKey secondaryKey;
public PrimarySecondaryKeyPair(TPrimaryKey primaryKey, TSecondaryKey secondaryKey) {
this.primaryKey = primaryKey;
this.secondaryKey = secondaryKey;
}
@Override
public int compareTo(MyCollection<T, TPrimaryKey, TSecondaryKey>.PrimarySecondaryKeyPair o) {
return secondaryKey.compareTo(o.secondaryKey);
}
}
public void put(T object, TPrimaryKey primaryKey, TSecondaryKey secondaryKey) { // put by primaryKey
primaryKeyMap.put(primaryKey, object);
PrimarySecondaryKeyPair keyPair = new PrimarySecondaryKeyPair(primaryKey, secondaryKey);
int insertionPoint = Collections.binarySearch(primarySecondaryKeyList, keyPair);
primarySecondaryKeyList.add((insertionPoint > -1) ? insertionPoint : (-insertionPoint) - 1, keyPair);
}
public T getByPrimaryKey(TPrimaryKey primaryKey) {
return primaryKeyMap.get(primaryKey);
}
public T getByIndex(int index) {
return getByPrimaryKey(primarySecondaryKeyList.get(index).primaryKey);
}
public void deleteByPrimaryKey(TPrimaryKey primaryKey) {
primaryKeyMap.remove(primaryKey);
for (int i = 0; i < primarySecondaryKeyList.size(); i++) {
if (primarySecondaryKeyList.get(i).primaryKey.equals(primaryKey)) {
primarySecondaryKeyList.remove(i);
}
}
}
public void deleteByIndex(int index) {
primaryKeyMap.remove(primarySecondaryKeyList.remove(index).primaryKey);
}
}
这个类(我认为)做你想要的,它不会不必要地存储任何东西。
put()
O(log n)
时间(以便通过二级密钥排序)。
来自这个使用的Collections.binarySearch()
方法的JavaDoc:
该方法在
log(n)
时间内运行“随机访问”列表(其提供接近恒定时间的位置访问)。
( primarySecondaryKeyList
是“随机访问”列表,因为它使用ArrayList
)。
通过主键获取对象的平均O(1)
时间O(n)
如果主键类型具有非常糟糕的散列函数,则最坏情况变为O(n)
)。
(见https://en.wikipedia.org/wiki/Hash_table )
O(1)
时间按二级键排序,因为这是基于获取主键(除非您想要将集合中的每个对象存储两次,这将占用两倍,否则必须这样做)空间)。 O(1)
时间。 O(n)
通过主键删除的最坏情况(从主键映射中删除很容易,但必须迭代次要到主键列表) 但是,请注意,如果您的主键只是一个Integer
或一个Long
,最坏情况下O(n)
将永远不会发生,因为它们的哈希函数只是它们的数值,因此它们非常准确(通常会导致O(1)
时间对于get()
s)。
以下示例假定您将使用Long
s作为主键 存储String
,并将Integer
作为辅助键存储 。 但是,该类是通用的,因此您可以使用任何类型的主键存储任何类型的对象(只需确保它具有相当好的hashCode()
函数!)和任何与自身可Comparable
辅助键(所有原始Number
包装器) ,像Integer
, Long
, Short
等,已经可以自己Comparable
了)。
要使用默认初始容量进行初始化:
MyCollection<String, Long, Integer> myCollection = new MyCollection<String, Long, Integer>();
初始容量为50:
MyCollection<String, Long, Integer> myCollection = new MyCollection<String, Long, Integer>(50);
将字符串"hello"
与主键937234L
和辅助键2
放在一起:
myCollection.put("hello", 937234L, 2);
......其他一切都应该是自我解释的;)
这应该符合您想要的要求和收集类型。
希望它有所帮助。 :)
(主键和对象的地图将提供一半的访问权限,排序的列表将提供另一半。如何根据我的要求组合这些?)
public class YourCollection{
private Map<UserObject> yourMap;
private List<UserObject> yourList;
public void add(UserObject obj){
yourMap.put(obj.primaryKey, obj);
yourList.add(obj);
//sort list on secondaryKey
}
public UserObject get(String key){
return yourMap.get(key);
}
public UserObject get(int index){
return yourList.get(index);
}
}
这只是基本的shell,但这个想法就在那里。 您选择哪种类型的列表和哪种类型的地图取决于您。 你可以/也应该为这个类添加泛型。
编辑 - 此外,没有针对特定问题的最佳方法。 你必须考虑不同方法的利弊,并根据你的目标权衡它们。 例如,你需要这个来占用最少的内存吗? 您是否需要使用最少的CPU周期? 您是否需要它才能成为最容易编写和维护的代码? 或者你只是想把一些有用的东西放在一起? 我实际上并没有要求你回答这些问题,但是在考虑这类问题时你应该考虑它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.