我有一个Tweet对象列表(本土类),我想使用Levenshtein距离根据文本删除 NEARLY 重复项。我已经通过散列推文删除了相同的副本。文本,但现在我想删除相同但最多2-3个不同字符的文本。由于这是O(n ^ 2)方法,我必须检查每个推文文本以及所有其他推文。到目前为止,这是我的代码:
int distance;
for(Tweet tweet : this.tweets) {
distance = 0;
Iterator<Tweet> iter = this.tweets.iterator();
while(iter.hasNext()) {
Tweet currentTweet = iter.next();
distance = Levenshtein.distance(tweet.getText(), currentTweet.getText());
if(distance < 3 && (tweet.getID() != currentTweet.getID())) {
iter.remove();
}
}
}
第一个问题是代码在某些时候抛出ConcurrentModificationException并且永远不会完成。第二个:我可以做比这个双循环更好的事情吗?推文列表包含近400,000条推文,因此我们正在讨论1600亿次迭代!
答案 0 :(得分:-1)
这个解决方案适用于手头的问题(到目前为止已经测试了可能的输入),但是如果你没有实现完整的比较合同以返回1,0和-1,那么删除重复项的正常设置操作将无法工作。
为什么不使用只有不同值的Set实现自己的比较操作。它将是O(n log(n))。
Set set = new TreeSet(new Comparator() {
@Override
public int compare(Tweet first, Tweet second) {
int distance = Levenshtein.distance(first.getText(), second.getText());
if(distance < 3){
return 0;
}
return 1;
}
});
set.addAll(this.tweets);
this.tweets = new ArrayList<Tweet>(set);
答案 1 :(得分:-1)
至于 ConcurrentModificationException :正如其他人所指出的那样,我正在从列表中删除我也在外部for-each迭代的元素。将for-each更改为正常以解决问题。
至于O(n^2)
方法:没有&#34;更好&#34;关于其复杂性的算法,而不是O(n^2)
方法。我想要做的是一个全面的&#34;全部&#34;比较找到几乎重复的元素。当然,有一些优化可以降低n
的总容量,并行化以同时解析原始列表的子列表,但复杂性始终是二次的。