【问题标题】:Removing an Element of a <String> ArrayList-Java删除 <String> ArrayList-Java 的元素
【发布时间】:2018-11-29 01:59:07
【问题描述】:

对于一个 java 家庭作业,我们被分配初始化一个包含字典单词的字符串数组列表。如果单词不是我们生成的长度,那么它们将从 ArrayList 中删除。以下代码不起作用。

public static int randLength() {
        int range=(RAND_MAX-RAND_MIN)+1;
        int randomNum=(int)(Math.random()*range)+RAND_MIN;
        return randomNum;
    }

此功能正常工作。

int randomLength=randLength();
      System.out.println(randomLength);
      for(int i=0;i<dictionaryList.size()-1;i++) {
          if(dictionaryList.get(i).length()!=randomLength) {
              System.out.println("The lucky word is " + dictionaryList.get(i));
              dictionaryList.remove(i);
          }
      }

然而,事实并非如此。 dictionaryList 是使用单词文本文件初始化的。我的是, “苹果” “啤酒” “查理” “小狗” “大象” “迷雾” 在某些情况下,上面的代码确实会删除不属于 randomLength 值的单词。但是,它不会将它们全部删除。任何帮助将不胜感激。

【问题讨论】:

  • 也许只是i &lt; dictionaryList.size(),你为什么在这里减一?
  • 是的,这没有考虑到最后一个元素,但是更大的问题是我没有考虑到一旦元素被删除,arraylist 就会被缩短。这反过来并没有搜索数组列表的所有元素。 Mathias 的解决方案有效!感谢您的意见。

标签: java arraylist


【解决方案1】:

当您从 ArrayList 中删除一个项目时,您会跳过列表中的下一个项目,而不是检查它是否应该被删除。

例如,如果您列出的是“apples”、“beer”、“charlie”、“dogs”、“atom”、“elephant”,并且您应该删除的单词长度的随机数是 4 ( beer、dogs 和 atom 应该被删除),“atom”不会被删除。当 for 循环运行时,它运行如下:

i: 0,单词:“apples”,未删除

i: 1, word: "beer", 移除

i: 2, word: "dogs", 移除

i:3,单词:“大象”,未删除。

如果删除了一个元素,则必须将 i 减 1,以便检查所有元素。您可以通过将i-- 放在dictionaryList.remove(i) 之后的行中来做到这一点

这是因为当从 ArrayList 中删除一个元素时,它之后的所有元素都会向下移动以填充空间,这与 Array 不同。

此外,您的 for 循环应该使用 i&lt;dictionaryList.size() 而不是 i&lt;dictionaryList.size()-1 以检查最后一个元素。

您也可以使用 Iterator 来遍历您的 ArrayList,但如果您还没有学会它,您可能不想使用它。

【讨论】:

  • 啊啊啊啊啊。我什至没有想到这一点。感谢您解决了我过去 5 个小时的挫败感!非常感谢。
【解决方案2】:

最好使用迭代器移除元素,避免并发修改异常。

int randomLength=randLength();
Iterator<String> iter = dictionaryList.iterator();
while(iter.hasNext()) {
    String word = iter.next();
    if(word.length() != randomLength) {
        System.out.println("The lucky word is " + word);
        iter.remove();
    }
}

【讨论】:

    【解决方案3】:

    Java Collection 类是快速失败的,这意味着如果在某个线程使用迭代器遍历它时更改 Collection,iterator.next() 将抛出 ConcurrentModificationException。

    ie : 通常不允许一个线程在另一个线程对其进行迭代时修改 Collection

    避免多线程环境下的ConcurrentModificationException

    1. 您可以将列表转换为数组,然后对数组进行迭代。 这种方法适用于中小型列表,但如果 列表很大,那么它会对性能产生很大影响。
    2. 您可以在迭代时锁定列表,方法是将其放入 同步块。不推荐这种方法,因为它会 停止使用多线程的好处。
    3. 如果您使用的是 JDK1.5 或更高版本,则可以使用 ConcurrentHashMap 和 CopyOnWriteArrayList 类。这是推荐的方法 避免并发修改异常

    考虑下面这个快速失败的例子

    使用 ConcurrentHashMap:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-23
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 2014-08-28
      • 2012-04-25
      相关资源
      最近更新 更多