Java ArrayList删除不带集合的重复数据



我在从ArrayList中删除重复项时遇到问题。这是大学作业。这是我已经有的代码:

public int numberOfDiffWords() {
ArrayList<String> list = new ArrayList<>();
for(int i=0; i<words.size()-1; i++) {
for(int j=i+1; j<words.size(); j++) {
if(words.get(i).equals(words.get(j))) {
// do nothing
}
else  {
list.add(words.get(i));
}
}
}
return list.size();
}

问题出在numberOfDiffWords()方法中。填充列表方法工作正常,因为我的导师给了我一个样本字符串(包含4465个单词)来分析——打印words.size()给出了正确的结果。

我想返回删除所有重复项后的新ArrayList的大小。

words是ArrayList类属性。

更新:我应该提到,我只允许在这部分任务中使用基于动态索引的存储,这意味着没有基于哈希的存储。

因为这是一个赋值,所以我不打算写代码。然而,我建议采取不同的方法。

  • 在执行时遍历数组
  • 使用subList()方法构建从启动到当前元素(但不包括当前元素)的阵列视图
  • 使用contains()测试当前元素是否在上一步骤中构造的子列表中
  • 只需计算找到了多少不包含在前缀中的元素

我推荐的方法应该会使代码更加简单易懂。请注意,所有这些都是O(n2)解决方案(如果你想做对的话,这就是你的解决方案)。

如果赋值允许修改数组,则另一种方法是对数组进行排序。然后相等的元素将是相邻的,并且很容易计算出有多少是唯一的。这是一种O(n-log(n))方法。(你也可以只复制一个数组,这不会改变不对称的复杂性,但会减慢解决方案的速度。)

如果不使用某种类型的哈希函数(HashSetHashMap),您将不会得到比这更好的结果。

如果您打算使用该方法,那么这就是您的问题:修改If-then-else,使其不会在第二个循环中添加单词。使用布尔变量在内部循环中验证是否存在重复,如果没有重复,则在第二个循环后将单词添加到列表中。

您应该通过调用arraylist上的contains()方法来检查重复,而不是对整个长度运行循环。

word.subList(fromIndex, toIndex).contains(arg);

这样,您的代码将非常简洁。

如果使用嵌套的for循环结构进行迭代,删除每个元素的重复,然后将剩余元素添加到新数组中,则可以返回较小的数组。我不确定这是否是最快的方法,但它有效。

// Delete all dupes
for ( i=0; i<words.length; i++ ) {
String word = words[i];
for ( j=(i+1); j<words.length; j++) {
if (words[j] == words[i]) {
words[j] = null;
}
}
}
// Count the array w/o nulls
int countEl = 0;
for (i=0; i<words.length; i++) {
if (words[i] != null) {
countEl++;
}
}
// Make a new array
String[] newArray = new String[countEl];
for (i=0; i<words.length; i++) {
if (words[i] != null) {
countEl.push(words[i]);
}
}

如果你想让它更简单,试试这个

final ArrayList duplicateWords = new ArrayList() ;
ArrayList<String> words = new ArrayList() {
@Override
public boolean add(Object e) {
if( !contains(e) ) {
return super.add(e);
} else {
duplicateWords.add(e);
return false ;
}
}
};
System.out.println("Unique words : " + words.size());
System.out.println("Duplicate words : " + duplicateWords.size());

这是另一个答案。

最新更新