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 以了解可能对您有帮助的其他方法。
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();
}
}
}
这是我的代码:
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 以了解可能对您有帮助的其他方法。
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();
}
}
}