视图—-通过使用视图可以获得其他实现了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));
    }
}

java系统对接视图 java中的视图类_java系统对接视图


这是关于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");
    }
}