Java回忆录(四)-------集合

    Java集合类的三驾马车,Set:代表无序、不可重复的集合。List:代表有序、重复的集合;Map:具有映射关系的集合,JDK1.5后增加了Queue体系集合:代表一种队列集合实现,JDK1.5前Java丢失容器中对象(即引用)的数据类型;JDK1.5之后增加了泛型,Java集合能记住容器中对象的数据类型。

    由于数组中只能存储基本数据类型元素值和引用类型的确定数量的对象,所以Java创造集合类(容器类)来保存数量不确定的对象数据(即引用变量)和具有映射关系的数据。Java集合类主要由两个接口派生Collection和Map,它们是集合框架的跟接口。Collection接口->set接口->EnumSet类|SortedSet接口->TreeSet类|hashSet类->LinkedHashSet。最常用的三个类分别是HashSet、ArrayList、HashMap。iterator迭代器也是集合框架的成员,它主要用于遍历Collection集合中的元素。Iterator并不是集合元素本身传给了迭代变量,而是把集合中元素的值传给了迭代变量,因为在修改迭代变量的值对集合元素本身没有任何改变。如果程序的一条线程在迭代访问Collection集合元素,一条在修改,这将导致ConCurrentModificationException异常,因为迭代器采用的是fail-fast的机制,而不是显示修改的结果,这样可以避免共享资源引发的潜在问题。还可使用JDK1.5提供的foreach循环来迭代访问集合元素。foreach和迭代器的使用注意事项相同。

    Set接口:HashSet不能保证元素的顺序,而且当两个线程访问一个Set集合时,需要代码来保证其同步,元素值可以使null。HashSet判断两个元素相等的标准是两个对象通过equals相等且两个对象的HashCode()方法的返回值不同,否则将存储在两个不同的位置。但这和Set的设计相违背,所以在某个类的对象保存到HashSet集合中时,重写equals和hashCode方法是,应该尽量保证二者之一相等,另外一个也相等。hashCode相等于HashSet的索引(类似数组,但数组索引是连续的),即可以得到元素被保存的位置。HashSet的子类LinkedHashSet使用链表来维护元素的次序,使得元素看起来是按照顺序插入的。TreeSet元素有序,采用红黑树②的数据结构对元素排序,支持自然排序(通过Comparable接口里的CompareTo(Object obj)升序排列)和定制排序(使用Comparator来实现TreeSet的定制排序)。如果把一个对象添加进TreeSet时,该对象必须实现Comparable接口,否则程序将在第二次添加元素时出现ClassCastException异常。EnumSet是一个专为枚举类设计的集合类,它的所有值都是指定的枚举类型的枚举值,且顺序由Enum类内定义的顺序决定,EnumSet在内部以向量的形式存储,这种存储形式非常的紧凑高效,因为EnumSet对象占用的内存很小,运行效率很好。不允许加入null元素。

    List接口:代表一个有序的集合。每一个元素都有自己对应的顺序索引,元素可重复,默认按添加顺序设置元素的索引。List在Set的基础上增加了一个ListIterator增加了向前迭代的功能,而且还可通过add方法向List集合中添加元素。ArrayList和Vector实现类是List类的两个典型实现。他们都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态分配的Object[]数组,并带有一个capacity属性(封装的数组长度)。如果需要一次性添加大量元素时,可使用ensureCapacity增加,减少重分配的次数,提高性能。虽然Vector是线程安全的,ArrayList是线程不安全的,但通常使用ArrayList,因为Vector缺点很多。Vector提供了一个Stack子类,用于模拟栈的后进先出(LIFO)容器。Object peek(), pop(),push()。另外List还有一个LinkedList的实现,他是一个基于链表实现的List类,对顺序访问集合中的元素进行了优化,特别是当插入、删除元素时速度非常快,因为LinkedList即实现了List接口,也实现了Deque(双向队列)接口⑤。

    Queue接口:模拟了队列这种先进先出的数据结构。它有两个常用的实现类LinkedList(可被当做双向队列、栈、List使用)和PriorityQueue是一个比较标准的队列实现类,因为它是按照元素大小进行重新排序的,违背了队列的基本规则先进先出(FIFO),不允许插入null元素,PriorityQueue也有自然排序和定制排序的方式(与treeSet一样)。

    Map(字典、关联数组):用于保存具有映射关系的数据,Map中包含一个内部类:Entry,该类封装了一个key-value对,包含三个方法Object getKey(),getValue()、SetValue(),我们可以把MAP理解为一个特殊的Set,即Set里包含的集合元素时Entry对象,而不是普通的对象。HashMap和HashTable是Map接口的典型实现类,HashMap线程不安全,所以性能比线程安全的HashTable稍高,HashTable不允许使用null作为Key或者Value会报NullPointerException异常,HashMap可以。HashMap重写了toString()方法,打印格式如下{key1=value1...},尽量少用Hashtable类,可以使用Map对象的KeySet方法返回全部Key组成的Set对象。当自定义类作为HashMap、HashTable的key时,如果重写equals和HashCode()标准同HashSet。与HashSet类似的是,尽量不要使用可变对象作为HashMap、Hashtable的Key,如果使用,请尽量不要在程序中修改作为key的可变对象。与HashSet一样HashMap有一个LinkedHashMap子类使用双向链表来维护key-value对的次序,该链表实现了迭代顺序,该迭代顺序与key-value对的插入顺序保持一致。避免了需要对HashMap、Hashtable里的key-value进行排序,同时又可避免使用TreeMap所增加的成本。由于需要维护插入顺序,性能较HashMap略有降低,但在迭代访问Map里的全部元素时将有很好的性能,因为它以链表维护内部顺序。

     SortedMap接口和TreeMap实现类:同Set用法一样也有自然和定制排序。WeakHashMap与HashMap的区别在于,HashMap的key保留对实际对象的强引用,如果该HashMap对象不被销毁,则该HashMap对象所有key所引用的对象也不会被垃圾回收,对应的value也不会自动删除。因此当使用WeakHashMap对象的Key所引用的对象应该不具有强引用。否则将失去意义。IdentityHashMap是一个特殊的Map实现,他的key值要求很严格即key1==key2才算是相等。EnumMap创建时必须指定一个枚举类,从而将EnumMap和指定枚举类关联起来。

    Collections:操作Set、List、Map的集合工具类,提供了对集合元素的排序、查询、修改、将集合元素设置为不可变、实现同步控制等方法。Java常用的集合框架中的三个实现类HashSet、ArrayList、HashMap,通过Collections.synchronizedList(new ArratList())实现线程安全版本。通过emptyxxx、singletonxxx、unmodifiablexxx来实现不可变集合。向不可变的集合中添加、修改集合元素将会引发UnsupportedOperationException异常。

    Enumeration:此接口是Iterator迭代器的古老版本,它只用于遍历Vector、Hashtable、BitSet等古老的集合类。除非极端情况,否则都应该选择Iterator迭代器。

    ①hashCode的基本规则:当两个对象通过equals方法比较返回true时,这两个对象的hashCode值应该相等。对象中用作equals比较标准的属性,都应该用来计算hashCode值。

    ②红黑树:

    ③Comparable接口的常用类:BigDecimal、BigInteger以及所有数值型对应的包装类、Character、Boolean、String、Data、Time

    ④Set性能比较:HashSet比TressSet的性能好尤其是在添加查询元素时,因为TreeSet需要红黑树算法来维护集合元素的次序。所以当不需要保持元素的排序时,应用HashSet,HashSet的子类:LinkedHashSet对于普通的插入删除操作,比HashSet略慢,因为它需维护链表所带来的额外开销,因为有了链表,所以遍历则更快。EnumSet是Set中性能最好的,但是它只能保存同一个枚举类中的枚举值作为集合元素,上述的三个Set都是线程不安全的。如果手动保持其同步性应使用例如SortedSet s = Collections.synchronizedSortedSet(new TressSet(...));

    ⑤Arrays的asList(Object...a)是把一个数组或指定个数的对象转换成一个List集合。它是Arrays的内部类ArrayList实例,是一个固定长度的List集合,只能遍历访问集合里的元素,不可增加和删除,否则会引发运行时的UnsupportedOperationException异常。

     ⑥List性能比较:LinkedList与ArrayList、Vector实现机制完全不同,ArrayList、Vector内部以数组的形式来保存集合中的元素,因此随机访问集合元素有较好的性能(比Iterator性能要好,因为随机访问会被英社称对数组元素的访问);而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色(只需改变指针的地址),Vector实现了线程同步,各方面性能都有所下降。

     ⑦Properties类时Hashtable的子类,该文件在处理属性文件。可以把Map对象和属性文件关联起来,且Properties里的key、Value都是字符串类型,对外提供三个方法String getProperty(String key), String getProperty(String key, String value),Object setProperty(String key, String value),void load(InputStream inStream), void Store(OutputStream out, String comments),Properties也可以对Xml进行处理。

     ⑧Map性能比较:HashMap和Hashtable的效率大致相同,因为他们的实现机制几乎一样,但HashMap通常比HashTable(尤其是当在插入删除key-value对时比Hashtable更慢)略慢,因为需要实现同步。TreeMap比前两者慢,因为TreeMap需要额外的红黑树操作来维护key之间的次序。好处是TreeMap中的元素总是有序的。当TreeMap被填充以后,即可调用keySet()遍历取得key组成的数组,然后用toArray生成Key数组。接下来使用Arrays的binarySearch()方法在已排序的数组中快速地查询对象。只有在某些无法使用HashMap时才这么做使用TreeMap。LinkedHashMap比HashMAP慢,因为要维护保护链表来保持Map中key顺序。IdentifyHashMap性能没有出色之处,采用与HashMap相似的实现,但equals判断严格相等,EnumMap性能最好,但它只能使用同一个枚举类的枚举值作为key。

     ⑨HashMap和HashSet的性能选项:容量、初始化容量、尺寸、负载因子、负载极限。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值