java - 从List中删除几乎重复的内容

时间:2016-02-10 15:15:36

标签: java duplicates levenshtein-distance concurrentmodification

我有一个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亿次迭代!

2 个答案:

答案 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的总容量,并行化以同时解析原始列表的子列表,但复杂性始终是二次的。