繁体   English   中英

在数组列表中删除重复项

[英]Removing duplicates in an arraylist

只是免责声明:我第二次重复了我的Java mod,所以我的问题可能会有点简单,希望我听起来不会太愚蠢。

编写方法removeDuplicates,该方法将已排序的字符串ArrayList作为参数,并从列表中消除所有重复项。 例如,假设一个名为list的变量包含以下值: {"be", "be", "is", "not", "or", "question", "that", "the", "to", "to"}调用removeDuplicates(list);之后; 该列表应存储以下值: {"be", "is", "not", "or", "question", "that", "the", "to"}

因为这些值将被排序,所以所有重复项将被分组在一起。

我对此的尝试:

public static void removeDuplicates(ArrayList <String>a){
    for(int i=0;i<a.size();i++){
        String word=a.get(i);
        String word2=a.get(i+1);

        if(word.equals(word2)){
            a.remove(word);

        }
        else{
            System.out.print(word);

        }
    }
}

问题是当我用以下命令调用它时:

["duplicate", "duplicate", "duplicate", "duplicate", "duplicate"]

它返回indexoutofbound 我了解到与remove方法有关,它与i=i-1有关。 试图在这里和那里插入它,但是不起作用。 但是我很困惑,因为这适用于我的代码。 当我用以下方式调用它时:

["be", "be", "is", "not", "or", "question", "that", "the", "to", "to"]

有用。

您的实现存在缺陷。

String word=a.get(i);
String word2=a.get(i+1);

当您到达最后一个元素时,将超出范围。

其次,当您直接从arraylist进行迭代时,您将删除元素,这将不起作用。 您改为迭代器。

我建议您将返回类型更改为ArrayList<String>并使用Set消除重复项。 这是如何做 :

public static ArrayList<String> removeDuplicates(ArrayList <String>a){
    return new ArrayList<String>(new HashSet<String>(a));
}

或者,在您当前的代码中,将for循环的上限更改为a.size()-1

for(int i=0;i<a.size()-1;i++) // this should prevent arrayindexoutofbound exception.

您有两个错误:第一个错误是您尝试访问不存在的对象。 i = a.size()String word2=a.get(i+1)不存在!

另一个错误是在遍历列表时删除元素。

您应该改为使用iterator

不使用迭代器即可解决此问题的方法是:使用:

for(int i=0;i<a.size() - 1;i++){

和:

if(word.equals(word2)){
    a.remove(word);
    i--;
}

您可以使用Set将添加到其中的元素删除重复的元素

您的for循环应为i < a.size() - 1

假设大小为4。当对i = 3进行迭代时,将获得word2的indexoutofbound,尝试访问索引4的值,该值实际上是从0到3rd的索引。

void unique (ArrayList<String> a)
{
  if( a.length() == 0 )
      return;

  int result = 0;
  int first = 0;
  int last = a.length();
  while (++first<last)
  {
      String r = a.get(result);
      String cur = a.get(first);
      if( !cur.euqals(r) )
          a.set(++result,cur);
  }
  a.removeRange(++result,last);
}

我希望此代码块可以为您提供帮助。

好吧,所以我将向您介绍语法和相当多的列表迭代概念。 振作起来,并准备好使用Java 7 API。


通过简单的步骤可以解决此问题:

  • 遍历列表。
  • 检查列表中的相邻元素。
    • 如果它们匹配,请将其删除。
    • 否则,别说了。
  • 返回结果非重复列表。

假设:

  • 假定具有与其他重复元素不相邻的重复元素的列表表现出非Set行为-也就是说,如果我输入了[A,B,B,A],我希望[A,BA]为输出。 这就是为什么我建议为此使用Set的原因。

仅使用remove()时要特别小心- 如果同时访问此列表,则将遇到ConcurrentModificationException 一种首选且稍微清洁一点的方法是改为使用IteratorListIterator接口。

在迭代之前,我们有四个案例:

  • 空(无元素)-应被禁止,因为我们[实际上]保证不会有空列表
  • 单例(仅一个元素,无重复)
  • 二进制(两个元素,一个可能是重复的)
  • 多边形( n > 2个元素)

我们不得不考虑一个极端的情况-超过三个重复的元素。 这意味着,在进行迭代时,我们必须查看上一个下一个元素,以确定是否应删除它。

以这个示例输入为例:

[A, A, A, B, C, D]

如果我们以朴素的方法进行迭代(前进时看着i + 1),那么我们将完全跳过一个元素。 不看左右,上面的结果将是:

[A, A, B, C, D]

为了解决这个问题,我们使用ListIterator ,它支持以前的操作。

使用天真的以前的方法来执行此操作会产生比以前更糟糕的结果-因为我们已经重置了当前光标的位置, 并且我们已经检查了它 ,因此前进到的下一个节点将被视为重复的错误! (具有讽刺意味的是,您不会摆脱前几个重复项。)

为了解决该问题 ,我们将光标重置为我们向左看之前的原始位置。

这是解决方案。 就我们上面定义的约束和预期行为而言,它可以在任何大小的列表上使用。

public List<String> removeDuplicates(final ArrayList<String> dupeList) {
    if(dupeList.size() == 0) {
        throw new IllegalArgumentException("Zero-length list == evil");
    }
    ListIterator<String> li = dupeList.listIterator();
    String w1;
    String w2;
    if(dupeList.size() == 1) {
        return dupeList;
    } else if(dupeList.size() == 2) {
        w1 = li.next();
        w2 = li.next();
        if(w1.equals(w2)) {
            li.remove();
        }
    } else {
        while(li.hasNext()) {
            if(li.hasPrevious()) {
                w1 = li.previous();
                li.next(); // explained a bit above
            } else {
                w1 = li.next();
            }
            if(li.hasNext()) {
                w2 = li.next();
                if(w1.equals(w2)) {
                    li.remove();
                }
            }
        }
    }
    return dupeList;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM