Java 高效的对象初始化
我正在创建一个模拟Twitter项目,该项目从一个较大的文本文件加载用户数据,该文件包含约360万行,格式如下: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毫秒) 现在,后半部分创建或查找跟随的用户
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,这很有意义。我一定会调查的!