【问题标题】:Remove multiple elements from ArrayList从 ArrayList 中删除多个元素
【发布时间】:2011-06-24 10:54:26
【问题描述】:

我有一堆索引,我想从ArrayList 中删除这些索引处的元素。我不能做一个简单的remove()s 序列,因为每次删除后元素都会移动。我该如何解决?

【问题讨论】:

    标签: java arraylist


    【解决方案1】:

    删除indexes处的元素:

    Collections.sort(indexes, Collections.reverseOrder());
    for (int i : indexes)
        strs.remove(i);
    

    或者,使用 Java 8 中的 Stream API:

    indexes.sort(Comparator.reverseOrder());
    indexes.stream().mapToInt(i -> i).forEach(l::remove);
    

    【讨论】:

    • Arrays.sort() 如果处理数组 ^^
    【解决方案2】:

    按降序对索引进行排序,然后将它们一一删除。如果您这样做,则删除不会影响您以后要删除的任何索引。

    如何对它们进行排序取决于您用于存储索引的集合。如果是列表,您可以这样做:

    List<Integer> indices;
    Collections.sort(indices, new Comparator<Integer>() {
       public int compare(Integer a, Integer b) {
          //todo: handle null
          return b.compareTo(a);
       }
    }
    

    编辑

    @aioobe 找到了我找不到的助手。而不是上面的,你可以使用

    Collections.sort(indices, Collections.reverseOrder());
    

    【讨论】:

    • 无需重新发明反向反向比较器。见my answer
    • @aioobe:谢谢,我认为在 Collections API 中有一种方法可以做到这一点,但我找不到它。
    • Arrays.sort() 如果你有一个数组 ^^
    • 我不明白。对数组进行排序会以何种方式改变事物需要移动的事实?例如,如果数组是{ 8, 5, 9, 1, 4, 7 },则用户想要删除154。如果您将数组反向排序为:{ 9, 8, 7, 5, 4, 1 },您就离实现目标更近了。
    • @Hatefiend:我没有说对进行排序,我说对索引进行排序。因此,在您的示例中,索引将为 1、3、4。排序为 [4、3、1]。按该顺序删除它们意味着后续删除的索引仍然有效。删除 4(在索引 4 处)后,5 和 1 仍将分别位于索引 1 和 3。以此类推。
    【解决方案3】:

    我来这里是为了删除特定范围内的元素(即 2 个索引之间的所有元素),然后发现:

    list.subList(indexStart, indexEnd).clear()
    

    【讨论】:

      【解决方案4】:

      您可以从最大索引开始向下删除元素,或者如果您有要删除的对象的引用,您可以使用removeAll 方法。

      【讨论】:

        【解决方案5】:

        您可以按相反的顺序删除索引。如果索引按 1,2,3 的顺序排列,您可以使用 removeRange(1, 3)。

        【讨论】:

        • 好像不能使用removeRange方法,只要不扩展ArrayList,因为方法是protected
        • @SanghyunLee 为什么是protected
        【解决方案6】:

        您可能希望将subList 方法与您要删除的索引范围一起使用,并且 然后调用 clear() 就可以了。

        (注意第二个参数是排他的——例如在这种情况下,我传递2意味着只有索引0和1将被删除。):

        public static void main(String[] args) {
            ArrayList<String> animals = new ArrayList<String>();
            animals.add("cow");
            animals.add("dog");
            animals.add("chicken");
            animals.add("cat");
            animals.subList(0, 2).clear();
            for(String s : animals)
                System.out.println(s);
        }
        

        }

        结果将是: 鸡 猫

        【讨论】:

        【解决方案7】:

        我认为南达是正确的答案。

        List<T> toRemove = new LinkedList<T>();
        for (T t : masterList) {
          if (t.shouldRemove()) {
            toRemove.add(t);
          }
        }
        
        masterList.removeAll(toRemove);
        

        【讨论】:

        【解决方案8】:

        您可以对索引进行排序,也可以使用迭代器并调用 remove()

        List<String> list = new ArrayList<String>();
            list.add("0");
            list.add("1");
            list.add("2");
            list.add("3");
            list.add("4");
            list.add("5");
            list.add("6");
            List<Integer> indexes = new ArrayList<Integer>();
            indexes.add(2);
            indexes.add(5);
            indexes.add(3);
            int cpt = 0;
            Iterator<String> it = list.iterator(); 
            while(it.hasNext()){
                it.next();
                if(indexes.contains(cpt)){
                    it.remove();
                }
                cpt++;
            }
        

        这取决于您需要什么,但在大多数情况下排序会更快

        【讨论】:

        • 我只是遇到了一个可以消除索引列表的情况,因为它们是记住要删除的行的解决方法。 Iterator.remove 很酷,可以轻松快速地解决一些删除问题。
        【解决方案9】:

        如果您确实有很多元素要删除(并且列表很长),那么迭代列表并将所有不被删除的元素添加到新列表中可能会更快,因为每个remove()-step in数组列表将删除后的所有元素一一复制。在这种情况下,如果您的索引列表尚未排序(并且您可以与主列表并行地对其进行迭代),您可能希望对 @987654322 使用 HashSet 或 BitSet 或一些类似的 O(1)-access-structure @检查:

        /**
         * creates a new List containing all elements of {@code original},
         * apart from those with an index in {@code indices}.
         * Neither the original list nor the indices collection is changed.
         * @return a new list containing only the remaining elements.
         */
        public <X> List<X> removeElements(List<X> original, Collection<Integer> indices) {
            // wrap for faster access.
            indices = new HashSet<Integer>(indices);
            List<X> output = new ArrayList<X>();
            int len = original.size();
            for(int i = 0; i < len; i++) {
               if(!indices.contains(i)) {
                   output.add(original.get(i));
               }
            }
            return output;
        }
        

        【讨论】:

          【解决方案10】:

          像这样对索引列表进行排序

          如果 2,12,9,7,3 顺序递减为 12,9,7,3,2

          然后这样做

          for(var i = 0; i < indexes.length; i++) { source_array.remove(indexes[0]); }

          这应该可以解决您的问题。

          【讨论】:

            【解决方案11】:

            如果您要删除的元素都组合在一起,您可以执行subList(start, end).clear() 操作。

            如果您要删除的元素是分散的,最好创建一个新的 ArrayList,只添加您希望包含的元素,然后复制回原始列表。

            编辑:我现在意识到这不是性能问题,而是逻辑问题。

            【讨论】:

            • .clear() 返回 void(以典型的 Java 方式)...你将如何保留子列表(如果需要)
            • @Jason List sublist = list.subList(start, end);删除列表 = 新列表(子列表); subList.clear();
            【解决方案12】:

            使用guava!您正在寻找的方法是 Iterators.removeAll(Iterator removeFrom, Collection elementsToRemove)

            【讨论】:

            • 我认为他有索引,而不是真正的元素。所以这对 imo 没有帮助。
            【解决方案13】:

            如果要将位置 X 删除到 Size

            //a is the ArrayList
            a=(ArrayList)a.sublist(0,X-1);
            

            【讨论】:

              【解决方案14】:

              假设您的 indexes 数组已排序(例如:1、3、19、29),您可以这样做:

              for (int i = 0; i < indexes.size(); i++){
                 originalArray.remove(indexes.get(i) - i);
              }
              

              【讨论】:

                【解决方案15】:

                我想我在上面没有看到的一种更有效的方法是创建一个新的 Arraylist 并通过将它们复制到新数组来选择哪些索引仍然存在。最后重新分配引用。

                【讨论】:

                  【解决方案16】:

                  我最终在这里进行了类似的查询,@aioobe 的回答帮助我找到了解决方案。 但是,如果您要填充索引列表以删除自己,可能需要考虑使用this

                  indices.add(0, i);
                  

                  这将消除在迭代之前对列表进行(昂贵的)反向排序的需要,同时从主 ArrayList 中删除元素。

                  【讨论】:

                    猜你喜欢
                    • 2013-02-24
                    • 1970-01-01
                    • 1970-01-01
                    • 2016-07-23
                    • 1970-01-01
                    • 2011-05-13
                    • 1970-01-01
                    相关资源
                    最近更新 更多