集合中视图与包装器概念,及Arrays.asList不可修改的原理解释
来源:互联网 发布:身份证psd源码 编辑:程序博客网 时间:2024/06/10 14:56
最近在学习《Java核心技术》集合的时候,才知道集合中视图的概念,在此做下记录,加深印象.. 在jdk中,我们对Collections和Arrays等包装类并不陌生,它提供了一些静态方法对集合的操作非常有用,比如
//生成一个有三个元素为“A”的List集合。List<String> nlist = Collections.nCopies(3,"A");
但是这个返回的list并不是传统的集合对象,而是视图对象,它实现了List接口,不需要付出建立数据结构的开销.包括Collections.singleton(“a”)等方法都返回的是视图,而不是集合类。视图对象可以说是具有限制的集合对象。这里的集合nlist 具有访问数组元素set,get的方法。但是如果调用改变数组的方法就会抛出异常。
还有其它一些视图,它具有不同的操作权限。
子范围视图:
集合类可以为自己创建一个子范围的视图,可以将任何操作应用于子范围视图上,并且子视图subList 的任何操作都会反映到list 集合中
List<String> list = new ArrayList<>();list.add("a");list.add("b");list.add("c");System.out.println(list); // a,b,cList<String> subList = list.subList(0, 1);subList.clear(); System.out.println(list); //b,c
不可修改视图:
上面产生的视图是可以修改的,如果想产生不可修改的视图,可以用
List<String> strings = Collections.unmodifiableList(a);
产生不可修改的视图。
同步视图:
如果多个线程访问集合,会造成同步问题,可以通过Collections的静态方法封装成一个具有同步访问方法的集合类。
List<String> strings1 = Collections.synchronizedList(a);
这里只是小总结一下,重要的还是视图的概念,具体可以见书上详细描述。
2017.3.29 视图不可修改的原理分析
在Arrays的工具类中,有一个数组变成List的方法
List<String> string = Arrays.asList(new String[]{"a", "b", "c"});
这里要注意,string是不可修改的List,我们看asList的内部代码
public static <T> List<T> asList(T... a) { return new ArrayList<>(a);}
返回的是ArrayList,可能会问,这没问题啊,为什么不能修改呢?此ArrayList非java.util包下,而是Arrays的内部类,它同样继承AbstractList,具有LIst的数据结构.
//java.util.Arrays.ArrayListprivate static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable{ private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { a = Objects.requireNonNull(array); } @Override public int size() { return a.length; } @Override public Object[] toArray() { return a.clone(); } @Override @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this.a, size, (Class<? extends T[]>) a.getClass()); System.arraycopy(this.a, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } @Override public E get(int index) { return a[index]; } @Override public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } @Override public int indexOf(Object o) { E[] a = this.a; if (o == null) { for (int i = 0; i < a.length; i++) if (a[i] == null) return i; } else { for (int i = 0; i < a.length; i++) if (o.equals(a[i])) return i; } return -1; } @Override public boolean contains(Object o) { return indexOf(o) != -1; } @Override public Spliterator<E> spliterator() { return Spliterators.spliterator(a, Spliterator.ORDERED); } @Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); for (E e : a) { action.accept(e); } } @Override public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); E[] a = this.a; for (int i = 0; i < a.length; i++) { a[i] = operator.apply(a[i]); } } @Override public void sort(Comparator<? super E> c) { Arrays.sort(a, c); }}
但是,AbstractList源码中,add,remove等方法是直接抛UnsupportedOperationException异常的,而在Arrays的ArrayList中,没有重写AbstractList抛出异常的代码。导致这种类型的ArrayList是只读的。
//java.util.AbstractListpublic void add(int index, E element) { throw new UnsupportedOperationException();}/** * {@inheritDoc} * * <p>This implementation always throws an * {@code UnsupportedOperationException}. * * @throws UnsupportedOperationException {@inheritDoc} * @throws IndexOutOfBoundsException {@inheritDoc} */public E remove(int index) { throw new UnsupportedOperationException();}
在java.util.ArrayList中,包括读写的方法都重写了
//java.util.ArrayListpublic void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size + 1); // Increments modCount!!System.arraycopy(elementData, index, elementData, index + 1, size - index);elementData[index] = element;size++;}/*** Removes the element at the specified position in this list.* Shifts any subsequent elements to the left (subtracts one from their* indices).** @param index the index of the element to be removed* @return the element that was removed from the list* @throws IndexOutOfBoundsException {@inheritDoc}*/public E remove(int index) {rangeCheck(index);modCount++;E oldValue = elementData(index);int numMoved = size - index - 1;if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--size] = null; // clear to let GC do its workreturn oldValue;}
那如果你确实需要 Arrays的方法从数组转换成List,而且又需要修改这个list,你可以用java.util.ArrayList构造类重新封装这个不可修改视图。
List<String> string = Arrays.asList(new String[]{"a", "b", "c"});ArrayList<String> strings2 = new ArrayList<>(string);
- 集合中视图与包装器概念,及Arrays.asList不可修改的原理解释
- Arrays.asList返回的集合
- 集合---视图与包装器
- java集合---视图与包装器
- Arrays.asList的使用及异常问题
- Arrays.asList的使用及异常问题
- Arrays.asList获取的list不可以直接使用remove
- Java中Arrays的asList()方法
- Java中Arrays.asList的使用
- Java中Arrays的asList()方法
- Java中Arrays.asList()
- Java集合框架官方教程(5):集合类的同步包装器/不可变包装器
- 使用Arrays的asList方法将数组变成List集合
- 关于Arrays的asList()
- Arrays.asList的用法:
- Arrays.asList的解析。
- Arrays.asList的用法
- Arrays.asList 的坑
- react native封装UI
- linux下cp目录时排除一个或者多个目录的实现方法
- Android之根据Uri获得图片或视频文件路径(解决4.4以上版本得不到路径的情况)
- 【LeetCode题解】链表Linked Lis
- Devexpress 11.1.8 .net 2.0时代最后一个版本
- 集合中视图与包装器概念,及Arrays.asList不可修改的原理解释
- 安卓-ListView基本使用
- spring mvc 框架搭建及详解
- 【JavaEE】经典JAVA EE企业应用实战-读书笔记11
- a标签跳转锚点到页面指定位置
- lwip之数据包pbuf
- 【PAT】1013. Battle Over Cities (25)
- openCV + Python 配置问题,同时 配置 pip 和安装Python相关的库 即 那个 whl 文件
- 给UIImage添加外边框圆