我正在创建一个模拟Twitter项目,该项目从一个包含大约360万行的大文本文件加载用户数据,格式如下:
0 12
0 32
1 9
1 54
2 33
etc...
第一个字符串标记是userId
,第二个标记是followId
。
此辅助方法的前半部分接收当前用户的ID,检查它是否存在并在必要时创建新用户。之后,followId
将添加到此新用户或现有用户的以下类型ArrayList<Integer>
列表中。
要读取约360万行,这不需要很长时间(9868 ms)。
现在,下半部分创建或找到关注的用户(followId
)并将userId
添加到他们的关注者列表中,但此附加代码会将时间延长到以指数方式读取文件(172744 ms)。
我尝试在整个方法中使用相同的TwitterUser
对象。所有添加方法(follow
,addFollower
)都是简单的ArrayList.add()
方法。我能做些什么来提高这种方法的效率吗?
请注意:虽然这与学校有关,但我不是要求我的解决方案的答案。我的教授允许这种慢速对象初始化,但我想了解如何让它更快。
private Map<Integer, TwitterUser> twitterUsers = new HashMap<Integer, TwitterUser>();
private void AddUser(int userId, int followId){
TwitterUser user = getUser(userId);
if (user == null){
user = new TwitterUser(userId);
user.follow(followId);
twitterUsers.putIfAbsent(userId, user);
} else{
user.follow(followId);
}
//adding the code below, slows the whole process enormously
user = getUser(followId);
if (user == null){
user = new TwitterUser(followId);
user.addFollower(userId);
twitterUsers.putIfAbsent(followId, user);
} else{
user.addFollower(userId);
}
}
private TwitterUser getUser(int id){
if (twitterUsers.isEmpty()) return null;
return twitterUsers.get(id);
}
答案 0 :(得分:3)
如果putIfAbsent(int, User)
执行了您期望它执行的操作,那就是:在插入之前检查它是否存在,为什么要在if
块中使用它?已检查用户是否在那里?
换句话说,如果提取用户返回null
值,则可以安全地假设用户不在那里。
现在我不太确定*putIfAbsent*
方法的内部工作方式(可能它会循环遍历地图中的键集),但直觉上我会期望正常put(int, User)
使用与您的一样大的地图进行更好的表现,直到扫描输入文件。
因此我建议尝试类似的事情:
user = getUser(followId);
if (user == null){
user = new TwitterUser(followId);
user.addFollower(userId);
twitterUsers.put(followId, user);
} else{
user.addFollower(userId);
}
也适用于上半场。