从 ArrayList 中删除给定长度的字符串?

Posted

技术标签:

【中文标题】从 ArrayList 中删除给定长度的字符串?【英文标题】:Removing Strings of given length from an 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。它所做的只是向后循环索引,以确保在删除元素时索引不会搞砸。 【参考方案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 一两年...

以上是关于从 ArrayList 中删除给定长度的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

从 pandas 数据框中删除句子长度超过特定字长的行

从仅给定一个属性的 ArrayList 中删除对象

ArrayList中remove()方法删除长度大于5的元素之后下标重定位的问题

无重复字符的最长字串

最长无重复字串

3:无重复字符的最长字串