如何禁用Java List的清除功能

时间:2016-04-12 07:03:14

标签: java arraylist

我有一个static List属性(例如ArrayList<String>),它在多个方法之间传递以添加/修改元素。已经很少有方法,并且在不久的将来会有很多方法可以实现。

所以我需要确保没有方法可以清除列表。到目前为止,我已使用空方法体覆盖了clear()方法。

我的方法如下:

private static List<String> singleList = new ArrayList<String>(){
    @Override
    public void clear() {
        //here I disabled clear() with empty method 
    };
};

public static void main(String[] args) throws IOException {
    addNumber(singleList);
    addDigit(singleList);
    addSign(singleList);
    System.out.println(singleList);
}


private static void addNumber(List<String> singleList) {
    singleList.add("1");
    singleList.add("2");
}

private static void addDigit(List<String> singleList) {
    singleList.add("A");
    singleList.add("B");
    singleList.clear();// Suppose, this line wrote accidentally, and I need to prevent it.
}

private static void addSign(List<String> singleList) {
    singleList.add("+");
    singleList.add("/");
}

还有更好的选择吗?

请建议我。

5 个答案:

答案 0 :(得分:3)

为此,您可以使用不变性。 而不是改变列表,只返回一个具有您想要的元素的不可变的列表。例如,您可以使用Guava ImmutableList,创建构建器并添加上一个列表和/或新元素。

Guava docs关于clear方法:

  

保证抛出异常并保持集合不被修改。

答案 1 :(得分:2)

我会添加UnsupportedOperationException以确保调用clear()的代码得到纠正。

如果代码依赖clear()工作,则不应该使用该集合。

如果代码不需要clear(),则不应该调用它。

答案 2 :(得分:2)

扩展 ArrayList更好的方法 - 虽然更详细 - 是撰写 ArrayList一个类,以防止清除。

基本上,创建一个实现List的类,并将其所有方法调用委托给另一个List实例,而不是clear

final class CannotClearList<E> implements List<E> {
  private final List<E> delegate;

  CannotClearList(List<E> delegate) {
    this.delegate = delegate;
  }

  @Override public boolean add(E element) {
    return delegate.add(element);
  }

  @Override public E get(int i) {
    return delegate.get(i);
  }

  @Override public void clear() {
    // Cannot "do nothing": that violates the definition of the
    // Collection.clear() method.
    throw new UnsupportedOperationException();
  }

  // etc, for all other methods.
}

除了你现在不能限制你无法清除的ArrayList(你可以重用它,例如LinkedList)的优势之外,这样做的真正好处在于:为了防止clear()工作,您还必须阻止List.subList返回的列表让clear()调用它们。

如果您通过扩展clear()阻止了ArrayList,那么您需要创建另一个类,该类也会阻止子列表中的clear()。但是,使用上面的CannotClearList,您只需将子列表包装在另一个CannotClearList

@Override public List<E> subList(int from, int to) {
  return new CannotClearList<>(delegate.subList(from, to));
}

请注意,clear()不是清除列表的唯一方法。你也可以:

  • 反复拨打remove;
  • 获取IteratorListIterator并在迭代时致电remove();
  • 使用空集合(或没有共同元素的集合)调用retainAll(Collection<?>)作为参数。

您应该仔细考虑是否也想要防止这些情况。

答案 3 :(得分:0)

您可以创建自己的UnClearableList扩展ArrayList - 然后在UnClearableList中覆盖clear()方法并在其中不执行任何操作(或者可能会抛出异常,具体取决于在你的设计上)。

然后在你处于“我想允许添加/删除但不清楚我的列表”的情况下使用UnClearableList。

您的做法在技术上是正确的。使用特殊的UnClearableList执行此操作可让您在其他类中重用它。 如果这只是一次学校练习,那就没有必要了。

答案 4 :(得分:0)

创建新类型或重载现有类型(如您所做)是常用的方法。此外,接口List明确允许禁用clear,因为它是可选操作。

来自JavaDoc:

/**
 * Removes all of the elements from this list (optional operation).
 * The list will be empty after this call returns.
 *
 * @throws UnsupportedOperationException if the <tt>clear</tt> operation
 *         is not supported by this list
 */
void clear();