Java Arraylist 按索引删除多个元素

Java Arraylist remove multiple element by index

这是我的代码:

for (int i = 0; i < myarraylist.size(); i++) {
        for (int j = 0; j < stopwords.size(); j++) {
            if (stopwords.get(j).equals(myarraylist.get(i))) {
                myarraylist.remove(i);
                id.remove(i);
                i--; // to look at the same index again!
            }
        }
    }

我有问题..删除元素后,所有索引总是改变,上面的循环太乱了。

举例说明: 我有 54 个数据,但是在删除元素后上面的循环变得混乱..所以只检查了 50 个数据。

是否有其他方法或修复我的代码以通过索引删除多个元素? 元素索引对我来说非常重要,删除另一个具有相同索引的数组列表。

在迭代时使用Iterator.remove()删除元素。

for (Iterator<String> iter = myarraylist.iterator(); iter.hasNext(); ) {
  String element = iter.next();
  if (element meets some criteria) {
    iter.remove();
  }
}

或使用 Google Guava 的 filter,其中 returns 过滤视图并保持原始列表不变。

Iterable<String> filtered = Iterables.filter(myarraylist, new Predicate<String>() {
  public boolean apply(String element) {
    return true of false based on criteria
  }
});

不确定为什么要按索引执行此操作,但您可以试试这个(未经测试):

int dynamicSize = myarraylist.size();
for (int i = 0; i < dynamicSize; i++) {
        for (int j = 0; j < stopwords.size(); j++) {
            if (stopwords.get(j).equals(myarraylist.get(i))) {
                myarraylist.remove(i);
                id.remove(i);
                i--; // to look at the same index again!
                dynamicSize--;
            }
        }
    }

看起来你想从另一个集合中删除一个集合..你应该使用 java.util.Collection改为#removeAll 方法

在迭代列表和删除对象时使用迭代器。

Iterator myListItr = myarraylist.iterator();
//Iterate on list 
    while(myListItr .hasNext()) {
    //if stop words is list of string then contains will work as it is. If its your custom object then override equals method.
        if(stopwords.contains( myListItr.next())){
    myListItr.remove();
}
}

您需要记住的一件事是,当您使用 ArrayLists 时,它们应该是多用途的,而不是 Arrays。您可以通过删除整个索引来缩短数组,向其添加索引,并使用 ArrayLists 做一些美妙的事情。

对于没有意识到或记得的人来说,这是一个常见问题,当您删除一个值时,ArrayList 索引(或任何正确的复数形式)会重新调整并且 ArrayList缩短。

尝试从 ArrayList 中删除元素时,您应该始终从 ArrayList 的末尾开始。

for(int x = arrayList.size() - 1; x > 0; x--)
{
    arrayList.remove(x);
}

这应该会为您提供您正在寻找的功能。查看 ArrayList API 以了解可能对您有帮助的其他方法。

使用ListIterator

ArrayList<String> list = new ArrayList<String>();
      // List : ["java", ".net", "javascript", "html", "css", "selenium", "image", "Spring"]

    ArrayList<Integer> indexes = new ArrayList<Integer>();
                                      // indexes : [5, 3, 2, 5, 0]
    // Sort the Indexes in Order to remove from back words. and make Unique
    TreeSet<Integer> uniqueSorted = new TreeSet<Integer>();
        uniqueSorted.addAll(indexes);

    // To remove all elements from the ArrayList and make its size = 0  
        indexes.clear(); 
        indexes.addAll(uniqueSorted);

    // Iterate form back, so that if size decreases also no problem.
    ListIterator<Integer> li = indexes.listIterator(indexes.size());

   // we can traverse a List in both the directions (forward and Backward).
        while(li.hasPrevious()) {
            int position = li.previous();
            list.remove(position);
        }

好的,这是一个很好解决的问题。 让我们从一个例子开始

我们有data = [5,2,7,3,9,34,63,23,85,23,94,7]

要删除的索引

int index[] = [5,2,7,9]

注意 :当您从数组中删除单个项目时,其他元素将移动 1。

如果我们使用 ArrayList 删除索引的元素,那么首先您需要对索引进行降序排序。

即索引 = [9,7,5,2] 然后从 index

中删除元素
ArrayList<Integer> data = Arrays.asList(new Integer[] {5,2,7,3,9,34,63,23,85,23,94,7});

for(int i=0;i<index.length;i++){
    data.remove(index[i]);
    }

这是一个简短的基准测试,它粗略地比较了从数组列表中删除元素的各种方法。按索引删除确实是一个坏主意,因为数组列表在每次操作时都会缩小其内部数组。小数组没有真正的区别,但如果你有大量索引要删除,它会花费很多。

Benchmark                                    Mode  Cnt   Score   Error  Units
CollectionsTest.filterToNewListViaLoop       avgt    2   4.425          ms/op
CollectionsTest.filterToNewListViaStream     avgt    2   5.410          ms/op
CollectionsTest.removeByIndexInReverseOrder  avgt    2  69.234          ms/op
CollectionsTest.removeByIterator             avgt    2   4.311          ms/op
CollectionsTest.removeViaRemoveAllMethod     avgt    2   4.145          ms/op

代码:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(MILLISECONDS)
@State(Scope.Benchmark)
@Warmup(iterations = 2)
@Measurement(iterations = 2)
public class CollectionsTest {

    private static final Random RANDOM = new Random();
    private static final int CONTAINER_SIZE = 100_000;
    private static final int REMOVE_COUNT = 10_000;

    private List<Foo> _container;
    private TreeSet<Integer> _indicesToRemove;
    private HashSet<Foo> _elementsToRemove;

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(CollectionsTest.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(opt).run();
    }

    @Setup(Level.Invocation)
    public void setup() {
        _container = generateContainerData(CONTAINER_SIZE);
        _indicesToRemove = generateIndicesToRemove(REMOVE_COUNT, CONTAINER_SIZE);

        _elementsToRemove = new HashSet<>();
        _indicesToRemove.stream().map(Foo::new).forEach(_elementsToRemove::add);
    }

    @Benchmark
    public void removeByIndexInReverseOrder() {
        int iterations = 0;
        for (int arrayIndex : _indicesToRemove.descendingSet()) {
            _container.remove(arrayIndex);
        }
    }

    @Benchmark
    public void removeByIterator() {
        _container.removeIf(foo -> _elementsToRemove.contains(foo));
    }

    @Benchmark
    public void filterToNewListViaStream() {
        List<Foo> elementsToKeep = _container.stream()
                .filter(foo -> !_indicesToRemove.contains(foo.id))
                .collect(Collectors.toList());
    }

    @Benchmark
    public void filterToNewListViaLoop() {
        List<Foo> elementsToKeep = new ArrayList<>(CONTAINER_SIZE - REMOVE_COUNT);
        for (Foo foo : _container) {
            if (!_indicesToRemove.contains(foo.id)) elementsToKeep.add(foo);
        }
    }

    @Benchmark
    public void removeViaRemoveAllMethod() {
        _container.removeAll(_elementsToRemove);
    }

    private List<Foo> generateContainerData(int size) {
        List<Foo> data = new ArrayList<>();
        for (int idx = 0; idx < size; idx++) {
            data.add(new Foo(idx));
        }
        return data;
    }

    private TreeSet<Integer> generateIndicesToRemove(int count, int containerSize) {
        TreeSet<Integer> data = new TreeSet<>();
        ThreadLocalRandom.current().ints(0, containerSize)
                .distinct()
                .limit(count)
                .forEach(data::add);
        return data;
    }

    public static class Foo implements Comparable<Foo> {
        private static final Comparator<Foo> COMPARATOR = Comparator.comparing(foo -> foo.id);

        public int id;

        public Foo(int id) {
            this.id = id;
        }

        @Override
        public int compareTo(Foo that) {
            return COMPARATOR.compare(this, that);
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Foo{");
            sb.append("id=").append(id);
            sb.append('}');
            return sb.toString();
        }
    }
}