【问题标题】:Java: How to remove objects from an Array depending on the condition?Java:如何根据条件从数组中删除对象?
【发布时间】:2011-10-02 13:52:17
【问题描述】:

我有一个对象数组(文件列表非常好)。如何遍历这个数组并删除一些对象(在 Java 中) - 取决于条件?

File[] files = file.listFiles();
for(File f: files) {
   if(someCondition) {
       // remove
   }
}

【问题讨论】:

  • 您不应该在迭代数组时从数组中删除元素。这可能会导致错误的索引。
  • @Harry Joy,你正在考虑一个列表。在数组中,您可以使用 null 更改对象/用下一个对象覆盖它,但您不能删除位置,因为数组无法调整大小。
  • @Harry Joy:你没有好好吸取教训。当您使用 Iterator 遍历 Collection (不是数组)并通过其他方式删除元素时(比如说list.remove(),您所说的适用
  • 将其转换为 List 类型并做任何您想做的事情,然后将其重新分配给您的数组。
  • @SJuan76 ,@Op De ZCirkel:我的错。我很抱歉。

标签: java iteration


【解决方案1】:

我认为解决问题的最佳 Java 方法是将数组转换为列表并使用允许删除对象的迭代器:

List<File> files = new ArrayList<File>(Arrays.asList(file.listFiles()));
Iterator<File> iterator = files.iterator();
while(iterator.hasNext()){
    File currentFile = iterator.next();
    if(someCondition){
        iterator.remove();
    }
    // other operations
}

如有必要,您甚至可以将其再次转换为数组 - 即使处理列表可能更方便...:

File[] filesArray = files.toArray();

【讨论】:

  • 您在正确的轨道上,但 iterator.remove() 将失败,并返回由 Arrays.asList() 返回的数组支持的列表。如果要添加或删除项目,则需要执行更繁琐的操作:List&lt;File&gt; files = new ArrayList&lt;File&gt;(Arrays.asList(file.listFiles()));
【解决方案2】:

您最好将 FilenameFilter 提供给 listFiles 并在那里应用条件。请参阅文件文档http://download.oracle.com/javase/6/docs/api/java/io/File.html

【讨论】:

    【解决方案3】:

    我们不能在一个步骤/操作中删除元素和调整数组大小。数组无法调整大小。

    使用List 或 (1) 标记您要删除的元素并 (2) 将您要保留的元素写入新数组。

    如果您想要继续使用数组,这里有一个解决方案(List 更容易):

    private File[] filter(File[] files) {
      boolean[] deleteFlags = new boolean[files.length];
      int deleteCounter = 0;
    
      // collection
      for (int i = 0; i < files.length; i++) {
        if (deleteConditionIsTrue()) {
           deleteFlags[i] = true;
           deleteCounter++;
        }
      }
    
      // create result
      File[] result = new File[files.length-deleteCounter];
      int gapCounter = 0;
      for (int i = 0; i < deleteFlags.length; i++) {
        if (deleteFlags[i]) {
          gapCounter++; // skip entry, has been filtered/deleted
        } else {
          result[i-gapCounter] = files[i];
        }          
      }
    
      return result;
    }
    

    【讨论】:

      【解决方案4】:

      JB Nizet 完全正确:

      1. 您不能从数组中“删除”元素

      2. 可以将元素设置为“null”。这有效地删除了它们(以一种 C 的方式),但它需要额外的逻辑,因此您不会意外地尝试引用 null 元素。

      3. 在所有条件相同的情况下,使用 List 可能会更好,它确实允许您插入和删除元素。

      PS: 如果您先验地知道不想要哪些元素,FileFilter 的想法是避免一开始就获得它们的好方法。

      【讨论】:

        【解决方案5】:

        您需要在数组中拥有对象的索引才能将其删除:

        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if(someCondition) {
                files[i] = null;       
            }
        }
        

        请注意,数组具有固定长度。删除元素不会缩小数组。如果需要,请使用List&lt;File&gt;,使用Iterator 遍历列表,然后使用迭代器的remove 方法删除当前元素。

        【讨论】:

        • 这需要在其他地方添加一些额外的逻辑,因为现在我们每次要使用数组元素时都必须测试null。我猜,他想resize 数组,而不是用null 替换值。但这只是一个猜测......
        • 我在回答中添加了一些关于这个问题的解释。谢谢。
        【解决方案6】:

        我建议将其转换为列表并使用 LambdaJ 过滤器操作: http://code.google.com/p/lambdaj/wiki/LambdajFeatures。其他库(如 Guava)中也提供了列表过滤器。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-07
          • 2019-07-02
          • 2012-10-30
          相关资源
          最近更新 更多