集合类库(六):集合类的相互包装
2009-09-18 00:00:00 来源:WEB开发网(1)问题的提出:
当我们即需要List结构的可重复存储,又需要Set中高效率的查找操作。怎么办?
(2)装饰者设计模式
不知道大家是不是还记得设计模式中的装饰者模式。我已经在《JDK与装饰者模式 》中用典型的Java IO框架举例说明了。其实除了IO框架,集合框架也用到了这种设计思想。这就是集合间的包装功能 。
我们现在回答上面的问题:
最好的解决办法就是:先用List存储好所有的数据,当需要查找某个元素的时候,将List对象包装成Set类型进行查找,然后返回List数据结构和Set的查找结果。将两种不同类别的功能合并使用,装饰者模式(包装器)无疑是最好的设计。
(3) Collection集合类的相互包装
所有实现Collection接口的集合类都有一种构造器,其参数时候存放了初始值的另一个集合。
Java代码
//ArrayList的包装构造器
public ArrayList(Collection<? extends E> c) {
.....
}
//LinkedList
public LinkedList(Collection<? extends E> c) {
.....
}
//HashSet
public HashSet(Collection<? extends E> c) {
.....
}
我们可以通过这种构造直接将一种Collection类对象包装成另一种。
Java代码
//Collection类的打包过程
import java.util.*;
public class TestDemo{
public static void main(String[] args){
ArrayList<String> list=new ArrayList<String>();
list.add("a1");
list.add("a1");
list.add("b1");
list.add("c1");
System.out.println("List ="+list);
HashSet<String> set=new HashSet<String>(list);//包装
System.out.println("Set ="+set);
}
}
//运行结果:
//List =[a1, a1, b1, c1]
//Set =[b1, a1, c1]
值得注意的是:包装过程中集合类的存储数据类型必须兼容Collection<? extends E>。也就是被 包装的集合中数据的类型必须是包装集合数据类型的子类或两者类型相同 。如下:被包装的ArrayList中的数据类型是Manager,它是包装的HashSet中数据类型Employee的子类。否则编译器不会通过。
这也是为了保证类型的自动向上转型的特性。被包装的类型可以通过包装操作自动向上转型成父类。
Java代码
//包装过程中泛型类型的兼容
import java.util.*;
class Employee{
}
class Manager extends Employee{
}
public class TestDemo{
public static void main(String[] args){
/*error : ArrayList<Employee> list=new ArrayList<Employee>();
HashSet<Manager> set=new HashSet<Manager>(list);*/
//正确:
ArrayList<Manager> list=new ArrayList<Manager>();
HashSet<Employee> set=new HashSet<Employee>(list);
}
}
顺便提一句: 集合框架中的Map类型是不能和Collection类型互相包装的,他们的数据结构毕竟相差太大了 。(你不想在商店买到的可乐里包装的是医用酒精吧)
这里提一下我一直的疑问:Collection的名字有点让人费解,刚学的时候还以为他就是所有集合类的基础接口,毕竟Collection的中文意思就是集合吗? 后来发现Map类型和Collection没有一点关系,不知道Java的设计者是怎么取名字的,或者有难言之隐吧。
(4) 集合和数组的转换
数组转化为集合:Array的asList()。
Java代码
String[] values=".....";
HashSet<String> hs=new HashSet<String>(Array.asList(values));
集合转化为数组:Collection的toArray()。
Java代码
HashSet<String> hs=new HashSet<String>();
Object[] o=hs.toArray();
千万要注意:toArray()方法返回的是一个Object[]数组。而且你无法将其强制类型转化成你需要的数组类型。
String[] array=(String[])hs.toArray(); //error
我们必须使用toArray的变体来做到这一点,为toArray传递一个长度为0的随意类型的数组。然后,返回的数组就是这个类型了。
String[] array=hs.toArray(new String[0]);
更多精彩
赞助商链接