1.泛型和类型安全的容器
使用java SE5之前的容器的一个主要问题是编译器允许你向容器中插入不正确的类型。
@SuppressWarnings("unchecked")
ArrayList apples = new ArrayList();
上面这段代码中,我们使用JAVA SE5所特有的注解来抑制了警告信息。@SuppressWarnings("unchecked")表示只有有关“不受检查的异常”的警告信息应该被抑制。
在没有使用泛型时,通过ArrayList的get()方法取出Apple对象时,得到的只是Object对象,必须将其转型为Apple对象。
预定义的泛型:
ArrayList<Apple> apple = new ArrayList<Apple>();
其中,尖括号括起来的是类型参数(可以有多个),它指定了这个容器实例可以保存的类型。通过使用泛型,就可以在编译期防止将错误类型的对象放置到容器中。并且,在将元素从List中取出时,可以直接获得相应的类型。因为List知道你保存的是什么类型,它会在调用get()方法时替你执行转型。
向上转型也可以像作用于其他类型一样作用于泛型:
ArrayList<Apple> apples = new ArrayList<Apple>();
apples.add(new Gala());
apples.add(new Fuji());
apples.add(new Apple());
2.基本概念
java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
1)Collection:一个独立元素的序列,这些元素都服从一条或多条规则。所有的Collection都可以用foreach语法遍历。
2)Map:一组成对的“键值对”对象,允许你使用键来查找值。
在理想情况下,我们编写的大部分代码都是在与接口打交道,并且唯一需要指定所使用的精确类型的地方就是在创建的时候。如下:
List<Apple> list = new ArrayList<Apple>();
使用接口的目的在于如果需要修改实现,只需要在创建的地方修改它,而无需修改其他的代码。如:
将List<Apple> list = new ArrayList<Apple>();修改为:
List<Apple> list = new LinkedList<Apple>();
但注意,这种方式并不总能有效,因为某些类具有额外的功能。
3.添加一组元素
在java.util包中的Arrays和Collections类中都有很多实用的方法。
Arrays.asList()方法接受一个数组或一个用逗号分隔的元素列表,并将其转换为一个List对象。Collections.addAll()方法接受一个Collection对象,以及一个数组或一个用逗号分隔的元素列表,将元素添加到Collection中。还有一个更加传统的addAll()方法,所有的Collection类型都包含该方法。
详见如下示例:
public class AddingGroups{
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5));
Integer[] more = {6,7,8,9};
collection.addAll(Arrays.asList(more));
Collections.addAll(collection,11,12,13);
Collections.addAll(collection,more);
List<Integer> list = Arrays.asList(11,12,13,14);
list.set(1,99);//可以,修改元素值
//list.add(21);
//list.remove(11);
}
说明:Collection的构造器可以接受另一个Collection来将自身初始化。但是,Collection.addAll()方法运行起来更快;另外,创建一个不包含元素的Collection,然后调用Collections.addAll()这种方式很方便,它是首选方式。
Collection.addAll()方法只能接受另一个Collection对象作为参数,因此它不如Collections.addAll()或Arrays.asList()灵活,并且这两个方法使用的都是可变参数列表。
注意: List<Integer> list = Arrays.asList(11,12,13,14);所创建的List对象,其底层仍然是数组,不能调整尺寸。当通过add()或delete()方法时会引发改变数组尺寸的尝试,这样会在运行时获得“Unsupported Operation”的错误。
再论Arrays.asList:
class Snow{}
class Crusty extends Snow{}
class Slush extends Snow{}
class Powder extends Snow{}
class Light extends Powder{}
class Heavy extends Powder{}
public class A {
public static void main(String[] args) {
List<Snow> list1 = Arrays.asList(new Crusty(), new Slush(), new Powder());
//List<Snow> list2 = Arrays.asList(new Light(), new Heavy());
ArrayList<Snow> list3 = new ArrayList<Snow>();
Collections.addAll(list3,new Light(),new Heavy());
List<Snow> list4 = Arrays.<Snow>asList(new Light(), new Heavy());
}
}
说明:当试图创建list2时,Arrays.asList中只有Powder类型,因此它只会创建List<Powder>而不是List<Snow>。然而Collections.addAll()工作的很好,因为它从第一个参数中了解到了目标类型是什么。
4.容器的打印
数组必须使用Arrays.toString()来打印,但是打印容器无需任何帮助。直接使用print即可。
5.Collection和Map介绍
1)Collection:List,Set,Queue(只允许在容器的一段插入对象,在容器的另一端移除对象)。
2)Map
List(有序,可重复):ArrayList,LinkedList
Set(不重复):HashSet(无序),TreeSet,LinkedHashSet。HashSet是获取元素最快的方法,如果储存顺序很重要,可以使用TreeSet,它按照比较结果的升序保存对象;或者LinkedHashSet,它按照被添加的顺序保存对象。
Map:HashMap(无序),TreeMap,LinkedHashMap。HashMap是获取元素最快的方法,如果储存顺序很重要,可以使用TreeSet,它按照比较结果的升序保存对象;或者LinkedHashMap,它按照被添加的顺序保存对象,同时还保留了HashMap的查询速度。
6.List
ArrayList:查询快,增删慢。
LinkedList:查询慢,增删快。
注意:(1)在List中间插入元素是可行的。
(2)确定一个元素是否属于某个List,获得某个元素的索引,从某个List中移除一个元素时,都会用到equals()方法。
list容器中的方法介绍:
contains():确定某个对象是否在容器中。
remove():移除一个对象。
indexOf():获得某对象在List中所处位置的索引编号。
subList():从较大的列表中创建出一个片段。
containsAll():判断一个列表是否包含另一个列表。
Collections.sort和Collections.shuffle():重新排列list
retainAll():获得两个List的交集。
removeAll(List list):移除list中包含的所有元素。
set(index,value):用value替代index索引处的元素。
重载的addAll():在初始List的中间插入新的列表,而不仅仅只能用Collection中的addAll()方法将其追加到表尾。
isEmpty():判断list是否为空。
clear():清空list。
toArray():将任意的Collection转换为一个数组。返回的是Object[]
toArray(new Object()):将产生指定类型的数组。