从 2 个指定标签之间的 ArrayList 中删除字符串

Deleting Strings from an ArrayList between 2 specified tags

我正在尝试删除 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>]

如何防止重复的字符串在删除范围之外被删除?

使用迭代器(并发修改安全)并删除元素而不是添加到删除列表

   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();
        }
    }
}

How can I prevent Strings who have duplicates to be deleted when they are outside of the deletion range?

通过元素索引而不是元素值来标识要删除的范围。有很多方法可以做到这一点,但这是我喜欢的一种:

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,但您需要更聪明地识别范围边界。