【问题标题】:Removing Strings of given length from an ArrayList?从 ArrayList 中删除给定长度的字符串?
【发布时间】:2013-10-27 10:12:16
【问题描述】:

我们得到一个 ArrayList 形式的单词列表,如下所示:

 public ArrayList<String> getListOfStrings(){
     ArrayList<String> list = new ArrayList<String>();
     list.add("This");
     list.add("is");
     list.add("an");
     list.add("exercise");
     list.add("to");
     list.add("illustrate");
     list.add("the");
     list.add("use");        
     list.add("of");
     list.add("ArrayLists");        
     list.add(".");
     return list;
    }

如何编写一个方法来删除该列表中的所有单词(即 ArrayList 中的所有对象),这些单词的长度由用户输入“len”?

我已经写了一个方法,列出了用户输入的所有长度为“len”的单词,并且有效,如下:

public ArrayList<String>getWordsWithLength(int len, ArrayList<String> lijst){
    ArrayList<String> list = new ArrayList<String>();
    for(String woord: lijst){
        if(woord.length()==len){
            list.add(woord);
        }
    }
    return(list);

}

但作为一个 java 初学者,我被困在如何删除长度为“len”的单词上。请帮忙! (我的印象是您首先从列表的末尾删除它们,就像从后到前一样)

【问题讨论】:

  • 您通过不将它们添加到您返回的新列表中来删除它们。
  • Backwards 也可以,但只能使用传统的 for 循环(属于 for(int i=list.size-1;i&gt;=0;i--) 种类。但首选 AbstractChaos 的解决方案
  • 谢谢,您能详细说明一下吗?我收到一个错误:“大小在 java.util.ArrayList 中具有私有访问权限”更不用说我没有 100% 遵循这段代码中发生的事情(我还是个初学者)
  • @user2895102 - 这是理查德的一个错字。它应该是list.size() 而不是list.size。它所做的只是向后循环索引,以确保在删除元素时索引不会搞砸。

标签: java arraylist bluej


【解决方案1】:

您当前遍历列表的方式不允许您在异常情况下将其删除,但迭代器可以。

Iterator<String> it = list.iterator();
while(it.hasNext()) {
 if([Condition]) {
   it.remove();
  }
}

【讨论】:

  • 你是对的,但分配指定使用上面 Richard Tingle 指定的简单“for”循环:“向后也可以工作,但只能使用传统的 for 循环(for( int i=list.size-1;i>=0;i--) 变种。不过,AbstractChaos 的解决方案更受欢迎——"
  • @user2895102 - 您也可以将上面的循环转换为 for 循环:for (Iterator&lt;String&gt; it = list.iterator(); it.hasNext();) ...
【解决方案2】:

您的方法已经可以用作删除,只需将== 更改为!=

public ArrayList<String> getStringsWithoutEqualLength(int len, ArrayList<String> lijst){
    ArrayList<String> list = new ArrayList<String>();
    for(String woord: lijst){
        if(woord.length() != len){ 
            list.add(woord);
        }
    }
    return(list);
}

如果您尝试从lijst 中删除元素,则只需将返回的列表重新分配给它。

ArrayList<String> yourList = ...;
yourList = instance.getStringsWithoutEqualLength(someLength, yourList);

您已经有效地删除了较长的元素,并且比使用Iterator 时做得更快。每次使用 Iterator 删除时,都必须调整后备数组的大小。

【讨论】:

  • 这实际上比使用Iterator 快吗?我会以大致相同的速度钉住它们。 Iterator 应该能够在恒定时间内进行移除,对吧?还是仅适用于链表?
  • @Cruncher 那是给LinkedListArrayList$Itr 调用 ArrayList#remove() 为底层数组执行 System.arraycopy
  • @SotiriosDelimanolis 但是你在做什么不是很有效吗?复制 ArrayList 减去 1 与 System.arraycopy 类似,只是您还实例化了更深层次的类?
  • @AbstractChaos 在此我们只复制一次数组。否则,您必须在每次删除时复制它。
  • @AbstractChaos 是的,取决于移除的数量。但如果我们在分析 Big-O,这会更快。
【解决方案3】:

您必须通过使用Iterator 来从List 中删除值,以防止ConcurrentModificationException

List<String> myList = getListOfStrings();
Iterator<String> it = myList.iterator();
while (it.hasNext()) {
   if(it.next().length() == 3){
    it.remove();
   }
}

【讨论】:

    【解决方案4】:

    您甚至可以通过添加布尔参数来使用相同的方法。

    public ArrayList<String>getWordsWithLength(int len, ArrayList<String> lijst, boolean complement){
        ArrayList<String> list = new ArrayList<String>();
        for(String woord: lijst){
            if((woord.length()==len) != complement){
                list.add(woord);
            }
        }
        return(list);
    
    }
    

    如果您将complement 传递为true,则如果没有length == len,则将为您提供所有内容。 complementfalse 一样会正常运行。

    【讨论】:

      【解决方案5】:

      虽然我认为 @SotiriosDelimanolis 的答案可能是您应该使用的,但我还想指出,使用 Java 8,您可以使用 StreamPredicate 轻松完成此操作:

       List<String> list2 = list.stream()
                            .filter(s -> s.length() != 3)
                            .collect(Collectors.toList());
      

      这是一个完整的测试类:

      import java.util.*;
      import java.util.stream.*;
      
      class Test {
        public static void main(String args[]) {
           ArrayList<String> list = new ArrayList<String>();
           list.add("This");
           list.add("is");
           list.add("an");
           list.add("exercise");
           list.add("to");
           list.add("illustrate");
           list.add("the");
           list.add("use");
           list.add("of");
           list.add("ArrayLists");
           list.add(".");
           System.out.println(list);
           List<String> list2 = list.stream()
                                .filter(s -> s.length() != 3)
                                .collect(Collectors.toList());
           System.out.println(list2);
        }
      }
      

      和我的测试输出:

      $ java Test
      [This, is, an, exercise, to, illustrate, the, use, of, ArrayLists, .]
      [This, is, an, exercise, to, illustrate, of, ArrayLists, .]
      

      【讨论】:

        【解决方案6】:

        在 Scala 中你会这样做

        list.filter(_.length != len)
        

        【讨论】:

        • Clojure 中你只需要(remove #(= (count %) len) my-list)——但 OP 没有询问 Scala 或 Clojure。但是,Java 8 确实 添加了一个 Scala 风格的 stream 包,这是我在回答中使用的。太糟糕了,我们不能指望人们真正拥有 Java 8 一两年...
        猜你喜欢
        • 2020-12-12
        • 2016-06-28
        • 2020-11-30
        • 1970-01-01
        • 1970-01-01
        • 2016-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多