我正在实现一个单例类,该类必须处理多个线程一次访问其数据结构。
该类有一个方法,如果数据结构已经包含myObject,则返回true,否则返回false。如果未看到对象,则将对象添加到数据结构中。
/* Schema */
/*
CREATE TABLE profile(
id SERIAL PRIMARY KEY,
username TEXT NOT NULL,
email TEXT NOT NULL,
privacy_settings JSONB
)
*/
/* Example Rows */
/*
[
{
id: 0,
username: 'Zero',
email: 'zero@zero.com',
privacy_settings: {
username: true,
email: false,
privacy_settings: false
}
},
{
id: 0,
username: 'One',
email: 'one@one.com',
privacy_settings: {
username: false,
email: true,
privacy_settings: false
}
},
]
*/
client.query('SELECT * FROM profile',[],(err,results) => {
if(err) throw err;
const filteredResults = results.rows.map(r =>
Object.keys(r)
.filter(key => r.privacy_settings[key] === true)
.reduce((obj, key) => {
obj[key] = r[key];
return obj;
}, {})
);
// Send to front end
res.send(filteredResults);
});
/* Results */
/*
[
{"username":"One"},
{"email":"one@one.com"}
]
MyObject具有两个成员变量boolean alreadySeen(MyObject myObject){}
和Instant expiration
,其中String id
作为确定数据结构是否包含id
的键。 我无法更改MyObject类。我需要定期检查数据结构中的myObjects myObject
,如果它们已过期,则将其删除。
因此,我正在寻找一种或多种可以快速添加,删除和搜索的数据结构, expiration
和 { {1}}。 我将主要添加元素并搜索元素是否存在,并定期清除以删除过期的元素。
像expiration
这样的映射为我提供了O(1)插入和删除功能,但通过O(n)搜索过期的对象将是我。
如上所述,我无法更改MyObject类。因此,我考虑为该类制作包装器,以便可以覆盖equals()和hashcode(),然后像id
那样做一个有序集合,这可以让我按到期日期对集合进行排序,然后可以快速找到最过期的。但是我相信这将是O(log n)进行搜索,删除。
我可以使用更好的结构吗?如果不是,从长远来看,我是否可以使用O(1)查找地图并添加但定期添加O(n)来删除到期时间呢?或更适合用O(log n)进行设置?
答案 0 :(得分:0)
您可以在O(1)处进行查找,添加和删除操作,但需要其他成本,如下所示:
我们需要两个映射,一个存储对象,键是id,值是对象,例如Map<id,MyObject>
,另一个可能要存储过期和MyObjects之间的关系,例如Map<Long,List<MyObjects>>
,键需要计算。 / p>
代码: 为了简单地编写代码,我修改了MyObject类:
class MyObject {
private long expiration;
private String id;
}
其他代码 私有地图dataSet = new ConcurrentHashMap <>(); 私人地图> obj2Expiration = new ConcurrentHashMap <>();
public boolean alreadySeen(MyObject myObject) {
boolean exist = dataSet.containsKey(myObject.getId());
if (!exist) {
dataSet.put(myObject.getId(),myObject);
Long expirateKey = myObject.getExpiration() / 5000;
List<MyObject> objects = obj2Expiration.get(expirateKey);
if (null == objects) {
objects = new ArrayList<>();
obj2Expiration.put(expirateKey,objects);
} else {
objects.add(myObject);
}
}
return exist;
}
@Scheduled(fixedRate = 5000)
public void remove() {
long now = System.currentTimeMillis();
long needRemode = now /5000 -1;
Optional.ofNullable(obj2Expiration.get(needRemode))
.ifPresent(objects -> objects.stream().forEach(o -> {
dataSet.remove(o.getId());
}));
}