2013-04-24 68 views
1

思考说:这是一种在Java中创建只读列表的方法吗?在Java中

要创建AbstractList的只读列表中,您必须农具get()和大小()。

它搞糊涂了,代码如下:

public class CountingIntegerList 
extends AbstractList<Integer> { 
    private int size; 
    public CountingIntegerList(int size) { 
    this.size = size < 0 ? 0 : size; 
    } 
    public Integer get(int index) { 
    return Integer.valueOf(index); 
    } 
    public int size() { return size; } 
    public static void main(String[] args) { 
    List list = new CountingIntegerList(30); 
    } 
} 

是列出一个只读的目录?为什么?

好吧,答案是肯定的,因为我扩展了AbstractList,如果setand被调用,它会丢失UnsupportedOperationException。如果我想得到一个不可修改的列表,Collections.unmodifiableList()是一个不错的选择。但要记住,他们两人都没有深入一成不变:

 List<StringBuilder> list = new ArrayList<StringBuilder>(); 
     StringBuilder sb = new StringBuilder(); 
     sb.append("hello"); 
     list.add(sb); 
     System.out.println(list); 
     list = Collections.unmodifiableList(list); 
     sb.append("world"); 
     System.out.println(list); 

有在CountingIntegerList一个flyweight pattern。因为每次get()被调用,它从整型的valueOf()源代码获得缓存:

public static Integer valueOf(int i) { 
    final int offset = 128; 
    if (i >= -128 && i <= 127) { // must cache 
     return IntegerCache.cache[i + offset]; 
    } 
     return new Integer(i); 
    } 

是否是正确的?

+0

这是可能的方法之一。 为什么?正如你所看到的,你不能添加任何元素到这个List ..(不是通过add方法。)我会建议有parameterised构造函数来接受初始List。否则你的不可修改列表将永远不会有任何数据 – 2013-04-24 13:33:47

+0

哪一部分让你感到困惑? – mikej 2013-04-24 13:34:30

+0

'你的不可修改列表将永远不会有任何数据'? – znlyj 2013-04-24 13:39:50

回答

4

因为set抛出一个UnsupportedOperationException,如果没有实现。见Api

+0

啊哈,也许我应该先熟悉api,谢谢! – znlyj 2013-04-24 13:34:50

1

传递的ArrayList到Collections.unmodifiableList()

返回指定列表的不可修改视图。该方法允许 模块为用户提供对内部列表的“只读”访问权限。 在返回列表“通过读取”到指定的 列表上查询操作,并试图修改返回的列表,无论是直接还是通过 其迭代器,都会导致UnsupportedOperationException异常。如果指定的列表是可序列化的,则返回的 列表将是可序列化的。 同样,如果指定列表中有 ,返回的列表将执行RandomAccess。

4

你可以包装在UnmodifiableList

List readOnlyList = Collections.unmodifiableList(yourList) 
5

您的列表它的只读(甚至是不可变的),因为add将抛出UnsupportedOperationException如将remove

AbstractList处理所有创建迭代器的工作, 为您计算哈希码和平等。这非常有帮助。 完全没有必要包装在unmodifiableList中。

后来你问是否AbstractList主要用于创建不可修改的列表。实际上它被用来创建任何类型的随机访问列表。在我的数据结构课程中,我们使用这样的抽象类来保存大部分实现列表类的工作。即使是Collection接口也有13种方法,除AbstractCollection之外,其余两种都是实现的。

有相关的类AbstractSequentialList可帮助创建非随机访问列表(如链接列表)。

+0

对不起,但我不清楚“完全不需要包装在不可修改的列表中”。你能解释我吗? – znlyj 2013-04-24 13:36:51

+0

您创建的列表没有任何方式可能发生变化。 unmodifiableList包装将确保addremove将引发异常,但由于它们无论如何,包装只是浪费空间和时间。 – 2013-04-24 13:39:02

+0

如果你扩展AbstractList,那么你不需要用'unmodifiableList'来包装它。 如果你想使用你现有的Collection类,比如ArrayList,那么你可以通过用'unmodifiableList'包装它来使其不可修改。 – 2013-04-24 13:40:14

0

这有点棘手。该列表不能改变和/或元素? ;)

StringBuilder builder = new StringBuilder(); 
    builder.append("Hello"); 
    List<StringBuilder> list = new ArrayList<StringBuilder>(); 
    list.add(builder); 

    Collection<StringBuilder> canNotChange = Collections.unmodifiableCollection(list); 
    builder.append(" World"); 
    System.out.println(canNotChange.iterator().next()); 
+0

但是你没有改变名单,不是吗?该清单像以前一样保存参考元素。 – znlyj 2013-04-24 14:01:32

+0

@znlyj yup。这是不可变的和深不可变的区别。这取决于你的需求。 – Eugene 2013-04-24 14:02:16

+0

所以我的'CountingIntegerList'不是非常不可变的。 'Collections.unmodifiableList'不能创建一个非常不可变的列表。 – znlyj 2013-04-24 14:14:50

相关问题