首先搞清楚Set,List,Queue都是Collection接口的子接口,Map是自成一派,跟Collection相对应。
Collection接口常用的方法:add(o),addAll(c),remove(o),removeAll(c),retainAll(c),contains(o),containsAll(c),iterator(),size(),isEmpty(),toArray(),clear()
Iterator接口是用来遍历类集的一个接口,不能独立存在。
Iterator接口常用的方法:
hasNext();next();remove();
注意两个重要的问题:
A 当Iterator在访问Collection子类对象的时候,一定不能调用Collection自己的方法去改变这个对象。只能使用Iterator的方法去改,如果要改,那么要关掉Iterator,改掉之后再去获取一次Iterator。注意区分Collection的remove(o)和Iterator的remove()这两个方法的区别,都是删除一个元素,但是,后者是Iterator接口的。
B Iterator接口访问的只是Collection子类对象中元素的副本。那么对iterator返回的值本身进行修改是不会影响到Collection去的,但是如果返回的是引用,而你又用引用来改变对象的值,那是改到Colleciton子类实例的元素中去的。(也正因为是副本所以为了保证一致性才不会让你在一个iterator访问中去修改collection集合元素),但是iterator的remove是有效的,是删除的Collection子类对象的元素。
Set是集合,相当于一个容器,特点是所有的元素不能够重复。Set接口跟Collection本身是没有区别的,只是不能元素重复。
Set常用的实现子类有:
注意:
A HashSet的add是如何判断元素重复的:先hashCode()再equals()两个都返回相等,那么元素重复。hashCode的返回值用来决定其存放位置,如果已经有元素了,那么通过equals去比较,如果相同那么重复元素,丢弃;否则就是冲突了,那么继续散列存放进去,所以这种情况会让HashSet的性能下降。
B 在HashSet的remove(obj)方法中,方法首先计算obj的hashCode,根据这个返回值作为哈希存储的位置;再判断是否equals,如果也返回true则删除,否则继续找直到找到或者找不到。所以如果你传入一个已经改变了值的旧对象那么它能找到这个存储的位置,但是在Collection中这个元素的值已经发生变化了,所以equals不会成功,所以不能删除了。所以说元素一旦插入HashSet中就不要改动元素的成员变量,特别是参与计算hashCode和equals计算的。
C LinkedHashSet 就是在HashSet的基础上再维护一张链表来保存元素的次序,这个次序是插入的次序。
注意:
A TreeSe的addt如何判断元素重复的:只要对象的compareTo(obj)方法返回0,那么元素相等重复,不add。TreeSet调用被add对象的compareTo(obj)方法与容器中的其他对象比较大小,然后根据红黑树结构找它的存储位置。如果相等,不add。
B 不要随便去修改TreeSet和HashSet容器中元素的关键字段,否则,都会混乱。
List作为Collection的子接口,可以使用Collection接口的全部方法,此外,由于List的有序(默认按元素的添加顺序设置元素的索引),所以有一些根据索引来操作元素的方法:
add(index,obj),addAll(index,c);根据index来找对象或者反过来根据对象来找index: get(index),indexOf(obj),lastIndexOf(obj);删除remove(index);设置指定index处的元素返回被替换的旧元素: Object set(index,obj);返回左闭右开的index子区间:List subList(fromIndex,toIndex);
注意:
List判断两个对象相等是只要对象的equals方法返回true就行。如List接口的indexOf(obj)方法等在利用obj找index的时候是通过对象的equals方法完成的。list会调用obj对象的equals方法去和已经存在的元素去比较,注意是调用的参数obj对象的equals方法。
ListIterator接口:
List另外提供了一个listIterator()方法返回ListIterator对象,ListIterator接口继承了Iterator接口,提供了专门操作List的方法:
hasPrevious(),previous(),add(o)特别注意Iterator是只能删除元素的,不能够add。
只能遍历访问该集合里的元素,不可增加、删除该集合里的元素(这么做会产生UnsupportedOperationException异常)。通过Arrays.asList(Object ... a)可变长度的参数方法,可以把一个数组或指定个数的对象转换成一个List集合。是固定长度的List集合,是Arrays.ArrayList内部类的实例。
Queue接口是表示队列的数据结构,其中常用的方法有:
添加元素:add(o),offer(o)
获取元素:获取后不删除的element(),peek();获取后删除的remove(),poll()。
重点研究下PriorityQueue子类和Deque子接口(双端队列)。
按其中存放的元素的大小顺序来排序,其中的元素可以是实现了Comparable接口或者是在建立PriorityQueue队列的时候传入一个Comparator对象。
双端队列接口其中常用的方法如下:
添加元素:addFirst(o),addLast(o),offerFirst(o),offerLast(o),push(o)
访问元素:删除的:pollFirst(),pollLast(),removeFirst(),removeLast(),removeFirstOccurrence(obj),removeLastOccurrence(obj) 不删除的:getFirst(),getLast(),peekFirst(),peekLast()
迭代器:descendingIterator()
ArrayDeque是基于数组实现的双端队列。
实现了Deque接口的List。内部以链表的形式来保存元素。
记住Map中的key有着类似于Set一样的特性。
Map接口常用方法:
clear(),containsKey(obj),containsValue(o), Set entrySet(),get(o),isEmpty(),Set keySet(),put(o,o),remove(o),size(),Collection values();
Map内部包含一个Entry内部类,该类封装了一个key-value对。Entry常用方法:
getKey(),getValue(),setValue(V value);
序列化就是将java对象转换成字节序列,方便对象存储到磁盘和在网络上传输。反序列化就是从IO流中恢复java对象。
一个类可以序列化一定要实现两个接口之一:Serializable或者是Externalizable接口。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt")); // ObjectOutputStream是一个处理流所以套在一个物理流上面。
oos.writeObject(具体的对象); // 这里才是真正的去序列化对象
ObjectInputStream ois = new ObjectInputStream( new FileInputStream("object.txt"));
(具体的类型) ois.readObject(); // 这里要注意做一个强制转化 // 这就是反序列化了
如果每一个对象在序列化的时候都直接序列化,那么当某个类的成员变量是一个引用类型的时候,当多个对象的该引用成员变量指向同一个对象的时候,那么这同一个对象就被序列化多次。到时候反序列化的时候将得到多个对象。
Java序列化机制规定:每一个序列化对象都有一个序列化编号,当序列化对象的时候,如果当前对象已经被序列化过,则只输出一个序列化编号;如果没有被序列化过,那么重新序列化这个对象。