java中视图和包装器_java集合---视图与包装器

视图—-通过使用视图可以获得其他实现了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 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 names = Arrays.asList("aa", "bb", "cc");

System.out.println(names);

//names.add("aaaaaa");同样会报错,原因同上

System.out.println(names.size());

System.out.println("----------我是分割线----------");

List set = Collections.nCopies(100, "default");

//实际上在这里只进行了一次赋值操作,详见jdk

System.out.println(set.get(0) == set.get(10));

}

}

ac191655ac3cf295801dca23cfa848a0.png

这是关于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 list = Arrays.asList(str);

System.out.println(list);

List group = list.subList(2, 5);

System.out.println(group);

System.out.println("----------我是分割线----------");

SortedSet set = new TreeSet(list);

SortedSet subset = set.subSet("aa", "dd");//大于aa小于dd不包含dd

System.out.println(subset);

subset.clear();//删除选中的项,并且直接反应在原映射中

System.out.println(set);

System.out.println("----------我是分割线----------");

SortedMap map = new TreeMap();

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 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 list = Collections.nCopies(5, "default");

List view = Collections.unmodifiableList(list);//该方法获取不可修改的视图

System.out.println(view.get(0));

view.add("aaa");//报错,获取的是不可修改视图

System.out.println("----------我是分割线----------");

List staff = new LinkedList();

lookAt(Collections.unmodifiableList(staff));

}

}

Collections.unmodifiableList 方法返回一个实现List接口的类对象。当然,lookAt方法 可以调用 List 接口中的所有方法, 而不只是访问器。但是所有的更改器方法,已经被重新定义为 抛出一个 UnsuportedOperationException 异常,而不是 将调用传递给底层集合;

注意:

不可修改视图并不是聚合本身不可修改,只是无法通过其投影出来的视图修改原集合。仍然可以实用集合的原始引用修改原集合。

由于视图只是包装了接口而不是实际的集合对象,所以只能访问接口中定义的方法。例如,LinkedList类有一些常用的方法,addFirst和addLast,他们都不是List接口方法,不能通过不可修改视图访问。

同步视图

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

Map map = Collections.synchronizedMap(new HashMap())

受查视图

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 str = new ArrayList();

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 str2 = new ArrayList();

List safe = Collections.checkedList(str2, String.class);

List string02 = safe;

string02.add(new Date());//编译器没有检测到这里的add异常

System.out.println("ok");

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值