Java 高效的对象初始化

Java 高效的对象初始化,java,performance,initialization,Java,Performance,Initialization,我正在创建一个模拟Twitter项目,该项目从一个较大的文本文件加载用户数据,该文件包含约360万行,格式如下: 0 12 0 32 1 9 1 54 2 33 etc... 第一个字符串标记是userId,第二个是followId 这个helper方法的前半部分接收当前用户的ID,检查它是否存在,并在必要时创建一个新用户。然后,将followId添加到此新用户或现有用户的以下类型列表ArrayList 要阅读360万行,这并不需要很长时间(9868毫秒) 现在,后半部分创建或查找跟随的用户

我正在创建一个模拟Twitter项目,该项目从一个较大的文本文件加载用户数据,该文件包含约360万行,格式如下:

0 12
0 32
1 9
1 54
2 33
etc... 
第一个字符串标记是
userId
,第二个是
followId

这个helper方法的前半部分接收当前用户的ID,检查它是否存在,并在必要时创建一个新用户。然后,将
followId
添加到此新用户或现有用户的以下类型列表
ArrayList

要阅读360万行,这并不需要很长时间(9868毫秒)

现在,后半部分创建或查找跟随的用户(
followId
),并将
userId
添加到他们的跟随者列表中,但此附加代码以指数方式延长了读取文件的时间(172744毫秒)

我尝试在整个方法中使用相同的
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);
}
private-Map-twitterUsers=new-HashMap();
私有void AddUser(int userId,int followId){
TwitterUser=getUser(userId);
if(user==null){
用户=新推特用户(userId);
user.follow(followId);
putIfAbsent(userId,user);
}否则{
user.follow(followId);
}
//添加下面的代码会大大降低整个过程的速度
user=getUser(followId);
如果(user==null){
用户=新推特用户(followId);
user.addFollower(userId);
putIfAbsent(followId,user);
}否则{
user.addFollower(userId);
}
}
私有TwitterUser getUser(int id){
if(twitterUsers.isEmpty())返回null;
返回twitterUsers.get(id);
}
如果
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);
 }

这同样适用于前半部分。

您不必检查
twitterUsers.isEmpty()
#getUser
中,如果未找到指定的键,
Map#get
将返回
null
。这不会大大减少运行时间,但它是多余的。您还可以发布
TwitterUser#follow
TwitterUser#addFollower
code吗?如果
putIfAbsent
是一个HashMap方法,而
follow
只是:1.)检查一下!ArrayList.contains(int)。。。2.)ArrayList.add(int)@JonnyHenlygood关于
isEmpty()
check。。关于这一点,我很傻,我没有意识到
putIfAbsent
HashMap
的一种方法。您是否考虑过使用另一个
HashMap
而不是
ArrayList
,因为
ArrayList
的查找时间是线性的?@JonnyHenly-oh-jeez,这很有意义。我一定会调查的!