为Java多线程问题选择正确的数据结构和设计

时间:2019-01-26 08:41:53

标签: java multithreading data-structures

我正在实现一个单例类,该类必须处理多个线程一次访问其数据结构。

该类有一个方法,如果数据结构已经包含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)进行设置?

1 个答案:

答案 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());
        }));
}