java集合---视图与包装器

来源:互联网 发布:mysql float 转换int 编辑:程序博客网 时间:2024/05/29 18:34

视图—-通过使用视图可以获得其他实现了Collection与Map接口的对象。映射类的keySet就是这样一个实例。初看起来,好像这个方法创建了一个新集,并将映射中的所有键都填进去,然后返回这个集。但是,事实并非如此。取而代之的是:keySet方法返回一个实现了Set接口的类对象,这个类的方法对原映射进行操作。这种集合就是视图。

轻量级集合包装器

Arrays类的静态方法asList将返回一个包装了普通java数组的List包装器,这个方法可以将数组传递给一个期望得到的列表或集合参数中:

package view;import java.util.Arrays;import java.util.Collections;import java.util.List;public class Testview01 {    public static void main(String[] args) {        String[] str = new String[10];        //这里返回的对象不是一个ArrayList。它是一个视图对象,带有访问底层数组的get和set方法        List<String> list = Arrays.asList(str);        list.set(2, "aaa");        System.out.println(list.get(2));        //改变数组大小的所有方法,例如add、remove方法等,都会抛出Unsupported OperationException异常        //list.add("aaa");        System.out.println(list.size());        System.out.println("----------我是分割线----------");        //asList可以接受可变数目的参数        List<String> names = Arrays.asList("aa", "bb", "cc");        System.out.println(names);        //names.add("aaaaaa");同样会报错,原因同上        System.out.println(names.size());        System.out.println("----------我是分割线----------");        List<String> set = Collections.nCopies(100, "default");        //实际上在这里只进行了一次赋值操作,详见jdk        System.out.println(set.get(0) == set.get(10));    }}

这里写图片描述
这是关于Collections.nCopies()方法的jdk源码截图,这里充分说明了它只进行了一次赋值。

区分Collections类和Collection接口

Collections类包含了很多实用的方法,这些方法的参数和返回值都是集合;不要与Collection接口混淆。

//这个方法将返回一个视图对象。这个对象实现了Set接口,返回的对象实现了一个不可修改的单元素集,        //而不需要付出建立数据结构的开销        Set singleton = Collections.singleton(names);        for(Object sets : singleton) {            System.out.println(sets);

子范围

package view;import java.util.Arrays;import java.util.List;import java.util.SortedMap;import java.util.SortedSet;import java.util.TreeMap;import java.util.TreeSet;public class TestView02 {    public static void main(String[] args) {        String[] str = new String[]{"aa", "dd", "ff", "cc", "qq", "bb"};        List<String> list = Arrays.asList(str);        System.out.println(list);        List group = list.subList(2, 5);        System.out.println(group);        System.out.println("----------我是分割线----------");        SortedSet<String> set = new TreeSet<String>(list);        SortedSet<String> subset = set.subSet("aa", "dd");//大于aa小于dd不包含dd        System.out.println(subset);        subset.clear();//删除选中的项,并且直接反应在原映射中        System.out.println(set);        System.out.println("----------我是分割线----------");        SortedMap<Integer, String> map = new TreeMap<Integer, String>();        map.put(1, "ff");        map.put(2, "aa");        map.put(3, "gg");        map.put(4, "ee");        map.put(5, "cc");        System.out.println(map);        SortedMap<Integer, String> submap = map.subMap(2, 4);        System.out.println(submap);        submap.clear();        System.out.println(map);    }}

不可修改视图

Collections 还有几个方法, 用于产生集合的不可修改视图。 这些视图对现有集合增加了一个运行时的检查。 如果发现试图对集合进行修改, 就抛出一个异常, 同时这个集合将保持未修改状态;(再次提醒:注意区分 Collection 和 Collections)

可以使用下列8种方法获得不可修改视图:

Collections.unmodifiableCollection
Collections.unmodifiableList
Collections.unmodifiableSet
Collections.unmodifiableSortedSet
Collections.unmodifiableMap
Collections.unmodifiableSortedMap
Collections.unmodifiableNavigableSet
Collections.unmodifianleNavigableMap
每个方法都定义于一个接口。如, Collections.unmodifiableList 与 ArrayList、LinkedList 或者任何实现了 List接口的其他类一起协同工作;

package view;import java.util.Collections;import java.util.LinkedList;import java.util.List;public class TestView03 {    public static void main(String[] args) {        List<String> list = Collections.nCopies(5, "default");        List view = Collections.unmodifiableList(list);//该方法获取不可修改的视图        System.out.println(view.get(0));        view.add("aaa");//报错,获取的是不可修改视图        System.out.println("----------我是分割线----------");        List<String> staff = new LinkedList<String>();        lookAt(Collections.unmodifiableList(staff));    }}

Collections.unmodifiableList 方法返回一个实现List接口的类对象。当然,lookAt方法 可以调用 List 接口中的所有方法, 而不只是访问器。但是所有的更改器方法,已经被重新定义为 抛出一个 UnsuportedOperationException 异常,而不是 将调用传递给底层集合;
注意:
不可修改视图并不是聚合本身不可修改,只是无法通过其投影出来的视图修改原集合。仍然可以实用集合的原始引用修改原集合。
由于视图只是包装了接口而不是实际的集合对象,所以只能访问接口中定义的方法。例如,LinkedList类有一些常用的方法,addFirst和addLast,他们都不是List接口方法,不能通过不可修改视图访问。

同步视图

  如果由多个线程访问集合,就必须确保集不会被意外的破坏。类库设计者使用视图机制来确保常规集合的线程安全,而不是实现线程安全的集合。例如,Collections类的静态synchronizedMap可以将任何一个映射表转换成具有同步访问方法的Map:
Map<String, Employee> map = Collections.synchronizedMap(new HashMap<String, Employee>())

受查视图

package view;import java.util.ArrayList;import java.util.Collections;import java.util.Date;import java.util.List;public class TestView04 {    public static void main(String[] args) {        ArrayList<String> str = new ArrayList<String>();        ArrayList string = str;        string.add(new Date());//到这里并没有发现添加的类型不符        Date date = (Date)string.get(0);        System.out.println(date);        /*String s = (String) string.get(0);//这里检测到类型不匹配        System.out.println(s);*/        System.out.println("----------我是分割线----------");        ArrayList<String> str2 = new ArrayList<String>();        List<String>  safe = Collections.checkedList(str2, String.class);         List string02 = safe;        string02.add(new Date());//编译器没有检测到这里的add异常        System.out.println("ok");    }}