高效的对象初始化

时间:2016-04-23 03:33:20

标签: java performance initialization

我正在创建一个模拟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对象。所有添加方法(followaddFollower)都是简单的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);
}

1 个答案:

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

也适用于上半场。