Java 容器集合(续)

Java 容器集合(续)

  关于集合框架上一篇已经讨论过了,此文作为一个补充,可能内容相对零散。

  (上一篇:Java 容器集合框架概览

  集合中存放的依然是对象的引用而不是对象本身。

  集合中存放的不能是原生数据类型,需要使用原生数据类型的包装类。

  当遍历集合中的元素时,可以使用迭代器。

  Collections这个类中包含了一系列的静态方法,用于操纵集合或者返回集合。

 

ArrayList和LinkedList的比较

  ArrayList和LinkedList类都是List接口的实现类。

  ArrayList底层采用数组实现,LinkedList底层采用双向链表实现。

  插入、删除操作,LinkedList的效率更高。

  当执行搜索操作时,ArrayList比较好。

  当向ArrayList添加一个对象时,实际上就是将该对象放置到了ArrayList底层所维护的数组当中;当向LinkedList中添加一个对象时,实际上LinkedList内部会生成一个Entry对象,该Entry对象的结构为:

Entry
{
    Entry previous;
    Object element;
    Entry next;
}

  其中的Object类型的元素element就是我们向LinkedList中所添加的元素,然后Entry又构造好了向前与向后的引用previous、next,最后将生成的这个Entry对象加入到了链表当中。

  换句话说,LinkedList中所维护的是一个个的Entry对象。

 

Set接口

实现类HashSet

  元素是无序的,且不允许重复。

  当使用add()方法把元素加入到Set中去时,会返回一个布尔值。当集合中不存在这个元素时,元素加入,元素加入成功时,返回true; 当集合中已经存在相同元素时,不加入当前元素,add()方法返回false

  当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code值是否与增加的对象的hash code值一致;如果不一致,直接加进去;如果一致,再进行equals()方法的比较,equals()方法如果返回true,表示对象已经加进去了,就不会增加新的对象,否则加进去。

  equals()方法和hashCode()方法都是Object类中的方法,如果没有进行覆写,则使用Object类中的实现。

  如果我们重写equals()方法,那么也要重写hashCode()方法,反之亦然。

  关于这两个方法的讨论可以参见Object类的讨论:

  http://www.cnblogs.com/mengdd/archive/2013/01/03/2842809.html

  Eclipse提供了自动生成hashCode()方法和equals()方法的功能:右键>Source>Generate hashCode() and equals()。

接口SortedSet

  SortedSet继承了Set接口,SortedSet的实现类是TreeSet。

  (可以参见前文Java 容器集合框架概览中的集合框架类图)。

  放入集合中的元素按照一定的顺序排列起来,加入元素时要求元素必须是可比较的,否则加入第二个元素时会抛出ClassCastException异常,因为它无法和之前已经存在的元素比较。

  TreeSet的构造方法中有一个

  TreeSet(Comparator<? super E> comparator)

  形式的方法,可以自己定义一个比较的方法传入:用一个类实现Comparator接口,然后重新定义其中的compare(T o1, T o2)方法,最后将这个类的对象传入上述TreeSet的构造方法。

 

Map

  Map映射,将键映射到它的值上。不能包含重复的键,每一个键最多可以映射到一个值。

  将键值对放入集合,用put方法:V put(K key, V value)。

  如果之前已经包含这个key,则用新的值更新旧的值。

  Map是一个接口,它的一个实现类是HashMap<K,V>。

  取出值,用get方法,参数是Key,返回时Value。如果不包含这个键的映射,则返回null。

  keySet()方法返回键的集合。返回Set<K>。

  values()方法返回值的集合。返回Collection<V>。

  说明键不能重复,但是值可以重复。

Interface Map.Entry<K,V>

  entrySet()方法返回map映射的集合。

TreeMap

  TreeMap是Map接口的另一个实现类,它的特点是对Key进行了比较,并且按照Key的顺序存放。

 

HashSet和HashMap

  HashSet底层使用HashMap实现的。当使用add方法将对象添加到Set当中时,实际上是将该对象作为底层所维护的Map对象的key,而value则都是同一个Object对象(该对象我们用不上)。

    // Dummy value to associate with an Object in the backing Map

    private static final Object PRESENT = new Object();

 

  HashMap的底层实现:

  HashMap底层维护一个数组,我们向HashMap中所放置的对象实际上是存储在该数组当中。

  当向HashMap中put一对键值对时,它会根据key的hashCode值计算出一个位置,该位置就是此对象准备往数组中存放的位置。

  如果该位置没有对象存在,就将此对象直接放进数组当中;如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找(Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上的某个对象的equals方法比较为false,则将该对象放到数组当中,然后将数组中该位置以前存在的那个对象链接到此对象的后面。(哈希链表)。

  Hashtable和Vector都是比较旧时代的东东,所以一般不用。

  Properties是Hashtable的一个子类,经常会被使用。

 

参考资料

  张龙老师视频教程。

  Java容器集合类的区别用法:

  http://www.cnblogs.com/sunliming/archive/2011/04/05/2005957.html

  Java集合类源码分析汇总:

  http://www.cnblogs.com/hzmark/archive/2013/01/05/JavaCollectionSum.html

  Java集合总结汇总(链接)

  http://www.cnblogs.com/Bob-FD/archive/2012/09/20/2695458.html

 

  几个关键接口和类的官方文档:

  Interface Collection<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html

  Interface List<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/List.html

  Class ArrayList<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

  Class LinkedList<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html

  Interface Set<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/Set.html

  Class HashSet<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html

  Class TreeSet<E>

  http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html

  Interface Map<K,V>

  http://docs.oracle.com/javase/7/docs/api/java/util/Map.html

  Class HashMap<K,V>

  http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html

  Class TreeMap<K,V>

  http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html

 

原文地址:https://www.cnblogs.com/mengdd/p/2868564.html