1.容器相关的接口和类的结构图
interface
(Collection) interface
(Map)
interface interface |
(Set) (List) HashMap
| | |
HashSet LinkedList ArrayList
2.Set和List是一个一个的元素往里装,Map是一对一对的元素往里装。
3.容器都位于java.util包里面,是建立在数组基础上发展起来的,里面存的仍然只是对象的引用,而不是对象本身,如果想要放原生数据类型进去,必须使用原生数据类型的包装类才能加入到容器里面去,当然,从Java 1.5以后,已经可以对基础数据类型进行自动地包装和拆包。
4.Set里面的元素无顺序,不能重复,List里面的元素有顺序,可以重复(互相equals)。对于要装进容器的类的对象,一定记住重写euqals和hashcode方法,因为2个元素是不是"相等"是通过equals方法来判定的。在获取元素的索引,删除元素的时候,都是通过equals来进行判定的。特别是针对set,如果想要保证单独创建的2个值一样的对象同时存在于set中,就要重写equals方法,要不然默认为是比较2者的地址值,既然是2个单独创建的对象,那么地址值肯定是不同的,通过比较,就会允许2个在值的意义上"相同"的元素被当作"不同"的元素来对待,造成混淆。
5.发现一个问题,其实呢,Collection的子接口以及相应的实现类,它们的方法增加得并不多,所以在定义时为了增强程序的健壮性,可以定义父类的引用指向实现类的对象,比如Collection c = new ArrayList(); 当然,通常情况下使用下一级接口就行了,比如 Set s = new HashSet();
这样的话,引用c只能使用在Collection中声明了的方法,如果将来想要更改容器的类型,很简单,可以直接改,不用担心使用了不该使用的方法。GoodPoint。
这个是多态的一个再典型不过的应用,有时候,我们使用了一种容器,比如ArrayList,最初的想法是用于查询,并不会涉及到过多的增删操作,但是随着时间的推移,可能会发现实际的使用过程中并不像事先想的那样,增删操作超过了查询,那么这个时候就要进行优化,将ArrayList换成LinkedList。你的设计中可能已经有数十处用到了这个容器对象,如果你使用的是多态的话,需要改动的只是一行代码,如果直接使用类进行的定义,那么有多少处,就要修改多少,维护成本非常高。
当然,在设计之初,尽量不要考虑太多这样和性能相关的东西,但是原理要遵循好。只是将来在实际的使用过程中,如果发现这个对性能造成了很大的开销,那么再来重构和优化也不迟。
6.再次提醒,通常如果你有对象要加到容器里面,最好是重写该类的eqauls和hashcode方法,因为remove的时候要比较2个对象是否相等,比较的默认方法是equals方法。而重写equals方法,必须重写hashcode方法,因为对象可能用来作为索引(key)。
当 Collection 接口没有为 Object.hashCode方法的常规协定添加任何约束时,为了满足 Object.hashCode 方法的常规协定,程序员应该注意任何重写Object.equals 方法的类必须重写Object.hashCode方法。需要特别指出的是,c1.equals(c2) 暗示着c1.hashCode()==c2.hashCode()。
7.Iterator是java.util中的一个接口,有3个方法,hasNext,next和remove。它可以对容器进行遍历。
与枚举不同的是:它允许调用者利用定义良好的语义在迭代期间从迭代器所指向的容器移除元素
8.增强for循环
1)它对于遍历array和collection的时候非常方便
2)有一些缺陷,除了简单遍历并读出其中的内容外,不建议使用增强for循环
9.容器里面放置的都是Object类型,所以取出来的也一定是Object类型,必须强制转换为其真正的类型,即放进去时的类型。
10. Iterator是遍历集合类的标准访问形式,比如你有一个List l = newArrayList();你可以对其进行元素添加和删除等等操作,但是呢,想遍历它的时候,最好的方法是,Iterator i =l.iterator(); 然后再利用Iterator里面的hasNext()方法来进行遍历,
while(i.hasNext()){
//这里赋个值 type element = (type)i.next();比如说如下:
String s = (String)i.next();
//然后打印一下什么的
}
11.对于Map,它并没有实现Iterable接口,那么如果想要对其进行遍历的话,要么就是得到一个entrySet,然后遍历,一个个地获取其键或者值。还有就是也可以直接获取一个keySet,然后遍历,根据键去一个个获取值。