#java #arraylist
Вопрос:
Я пытаюсь удалить все элементы списка массива между начальным и конечным тегом.
Мой список и мои теги:
String startTag = "<p>";
String endTag = "</p>";
List<String> elements = new ArrayList<>();
Допустим, мой список выглядит так:
[<text>, <p>, <text>, clean me, </text>, </p>, </text>]
Я хочу удалить только содержимое между разделенными тегами и самими тегами.
Это мой код для этого:
boolean delete = false;
List<String> remove = new ArrayList<>();
for(String element : elements) {
if(delete) {
remove.add(element);
}
if(element.startsWith(startTag)) {
delete = true;
remove.add(element);
}
if(element.endsWith(endTag)) {
delete = false;
remove.add(element);
}
}
elements.removeAll(remove);
}
Вот как выглядит мой список «удалить» после этого:
[<p>, <text>, clean me, </text>, </p>, </p>]
Итак, после удаления этих элементов из моего списка это выглядит так:
[]
Когда это должно выглядеть так:
[<text>, </text>]
Как я могу запретить удалять строки, у которых есть дубликаты, когда они находятся за пределами диапазона удаления?
Ответ №1:
Как я могу запретить удалять строки, у которых есть дубликаты, когда они находятся за пределами диапазона удаления?
Определяя диапазон для удаления по индексу элемента, а не по значению элемента. Есть много способов, которыми вы могли бы это сделать, но вот один, который мне нравится:
List<String> remainingElements = elements;
List<String> result = new ArrayList<>();
for (int start = remainingElements.indexOf(startTag);
start >= 0;
start = remainingElements.indexOf(startTag)) {
List<String> tail = remainingElements.subList(start, remainingElements.size());
int end = tail.indexOf(endTag);
if (end >= 0) {
List<String> range = tail.subList(0, end 1);
result.addAll(range);
range.clear();
remainingElements = tail;
} else {
break;
}
}
Обратите внимание, в частности, что подсписок поддерживается родительским списком, так что изменения в первом отражаются во втором.
Обратите также внимание, что представленные здесь детали соответствуют очевидной идее вашего исходного примера: они соответствуют первому появлению startTag
с первым появлением после этого endTag
. Это может быть не то, что вы на самом деле хотите, если вам нужно учитывать вложенность тегов. Например, результат с startTag = "<text>"; endTag = "</text>";
был бы [</p>, </text>]
. Вы все еще можете использовать subList
в таком случае, но вам нужно быть умнее в определении границ диапазона.
Комментарии:
1. Спасибо за подробный ответ и лучшее понимание того, как лучше решить проблему.
Ответ №2:
Используйте итератор (то есть безопасное изменение параллелизма) и удаляйте элементы вместо добавления в список удаления
boolean delete = false;
Iterator it = elements.iterator();
while(it.hasNext()) {
String element it.next();
if(delete)
it.remove();
if(element.startsWith(startTag)) {
delete = true;
it.remove();
}
if(element.endsWith(endTag)) {
delete = false;
it.remove();
}
}
}
Комментарии:
1. Потенциальная проблема с этим подходом: если
startTag
появляется в списке, ноendTag
не появляется, то весь хвост списка удаляется, даже если он не ограничен парой (startTag, endTag).