java集合详解

来源:互联网 发布:编程判断整数的奇偶性 编辑:程序博客网 时间:2024/05/19 02:31

Collection接口

collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。jdk不提供此接口的直接实现,它提供更具体的子接口(如SetList)实现。



 booleanadd(E o)
          确保此 collection 包含指定的元素(可选操作)。
 booleanaddAll(Collection<? extends E> c)
          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
 voidclear()
          移除此 collection 中的所有元素(可选操作)。
 booleancontains(Object o)
          如果此 collection 包含指定的元素,则返回 true
 booleancontainsAll(Collection<?> c)
          如果此 collection 包含指定 collection 中的所有元素,则返回true
 booleanequals(Object o)
          比较此 collection 与指定对象是否相等。
 inthashCode()
          返回此 collection 的哈希码值。
 booleanisEmpty()
          如果此 collection 不包含元素,则返回 true
 Iterator<E>iterator()
          返回在此 collection 的元素上进行迭代的迭代器。
 booleanremove(Object o)
          从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
 booleanremoveAll(Collection<?> c)
          移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
 booleanretainAll(Collection<?> c)
          仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
 intsize()
          返回此 collection 中的元素数。
 Object[]toArray()
          返回包含此 collection 中所有元素的数组。
<T> T[]toArray(T[] a)
          返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。


iterator接口

 booleanhasNext()
          如果仍有元素可以迭代,则返回 true
 Enext()
          返回迭代的下一个元素。
 voidremove()
          从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操作)。

Set接口

1.是Collection接口的一个子接口

2.不包含重复的元素,不存在e1.equals(e2)true 

3.由于提供的数据结构是数学意义上的集合概念的抽象,因此它需要支持对象的添加、删除、而不需提供随机 访问。Set接口继承Collection接口,所有原始方法都是现成的,没有引入新方法


HashSet类


 无序不重复非同步,集合元素可以是null,但只能放入一个null,当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对 象在HashSet中存储位置

TreeSet类

1.有序不重复非同步,不允许为null,是SortedSet接口的唯一实现类,支持两种排序式,自然排序 和定 排序,其中自然排序为默认的排序方式。定制排序使用Comparator接口,实现 int compare(T o1,T o2)

2.判断两个对象不相等的方式是两个对象通过equals方法返回false,或者通过CompareTo方法比较没返回0

3.自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小,将元素按照升序排列


总结:

1.TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值。 

2.HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复。 

3.HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例

4.HashSet和TreeSet是Set的两个典型实现,HashSet的性能总比TreeSet好(添加,查询操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序

5.HashSet还有一个子类LinkedHashSet,对于普通的插入,删除操作,LinkedHashSet比HashSet要慢一点点,这是因为维护链表所带来的开销。不过遍历集合时,LinkedHashSet就非常块

List接口

1.是collection的子接口

2.代表有序的集合 ,集合中每个元素都有其对应的顺序索引

3.允许使用重复元素,通过索引来访问指定位置的集合元素

ListIterator接口:

ListIterator接口是Iterator的子接口,提供了专门操作List的方法。

ListIterator接口新增的方法:

1)boolean  hasPrevious():返回该迭代器关联的集合是否还有上一个元素。

2)Object  previous():返回该迭代器的上一个元素。

3)void  add():在指定位置插入一个元素。根据上面的三个方法和解释,不难发现ListIterator新增加了向前迭代的功能,而且ListIterator还可以通过add方法向List集合中添加元素。

ArrayList和Vector:

ArrayList和Vector类都是基于数组实现的List类,ArrayList和Vector类封装了一个动态在分配的Object[ ]数组。

每个ArrayList或Vector对象有一个capacity属性,该属性表示他们所封装的数组的长度,当想ArrayList或Vector中添加元素时,它们的capacity会自动增加。

对于通常编程中,程序员无须关心ArrayList或Vector的capacity属性。但如果向ArrayList集合或Vector集合中添加大量元素时,可使用ensureCapacity方法一次性的增加capacity。这样可以提高性能。

ArrayList和Vector在用法上几乎完全相同(Vector是古老的集合,JDK1.0就存在了),但ArrayList集合是线程不安全的,当多条线程访问同一个集合时,如果有超过一条线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。而Vector集合则是线程安全的。无须程序保证集合的同步性。所以Vector的性能比ArrayList的性能低。

固定长度的List——数组的工具类 Arrays提供的asList()方法是把一个数组或指定个数的对象转换成一个List集合, 但这个List集合既不是ArrayList实现类的实例,也不是Vector实现类的实例,而是Arrays的内部类ArrayList实例。Arrays.ArrayList是一个固定长度的List集合,程序只能遍历访问该集合里的元素,不可增加,删除该集合中的元素。

LinkedList实现类:

它实现了List接口,还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双向队列。

Map接口

1.Map概述
    Map接口不是 Collection 接口的继承,Map<K,V>  Map集合类用于存储元素对(称作键和值),其中每个键映射到一个值,该接口描述了从不重复的键到值的映射。

2.Map子类

    1).HashTable,底层是哈希表数据结构,不可以存入null键和null值,线程同步,JDK1.0效率低
    2).HashMap,底层是哈希表数据结构,可以存入null键和null值,不同步,JDK1.2效率高
    3).TreeMap,底层是二叉树数据结构,线程不同步,可以用于Map键排序.

3.Map集合转为Set集合

    1).Set<K>keySet(),将所有的键存入Set集合,再使用迭代器获取value值
    2).Set<Map.Entry<K,V>>entrySet(), entrySet()方法返回一个实现Map.Entry接口的Set集合,集合中存放的是键           值对应关系,该关系是Map.Entry型                 

4.Map.Entry是Map接口的内部接口,getKey(): 返回条目的关键字,getValue(): 返回条目的值

HashMap 和 TreeMap

1.Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按顺序遍历键,那么TreeMap 会更好

2.根据集合大小,先把元素添加到 HashMap,再把这种映射转换成一个用于有序键遍历的 TreeMap 可能更快

3. 使用HashMap 要求添加的键类明确定义了 hashCode() 实现。有了TreeMap 实现,添加到映射的元素一定是可排序的

4.为了优化 HashMap 空间的使用,您可以调优初始容量和负载因子。这个TreeMap 没有调优选项,因为该树总处于平衡状态

总结:

Set子接口:无序,不允许重复,检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变

HashSet:以哈希表的形式存放元素,插入删除速度很快

TreeSet: 二叉树

List子接口:有序,可以有重复元素,和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变

        ArrayList:动态数组
        LinkedList:链表、双向队列、堆栈
        Vector是一种老的动态数组,线程同步的,效率低

Map接口:键值对、键不重复

HashTable,底层是哈希表数据结构,不可以存入null键和null值,线程同步,JDK1.0效率低
HashMap,底层是哈希表数据结构,可以存入null键和null值,不同步,JDK1.2效率高
TreeMap,底层是二叉树数据结构,线程不同步,可以用于Map排序

面试问题

2、什么是Iterator

   一些集合类提供了内容遍历的功能,通过java.util.Iterator接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用 Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合本省。

  3、Iterator与ListIterator有什么区别?

   Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。

  4、什么是HaspMap和Map?

   Map是接口,Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。

  5、HashMap与HashTable有什么区别?对比Hashtable VS HashMap

   两者都是用key-value方式获取数据。Hashtable是原始集合类之一(也称作遗留类)。HashMap作为新集合框架的一部分在Java2的1.2版本中加入。它们之间有一下区别:

  HashMap和Hashtable大致是等同的,除了非同步和空值(HashMap允许null值作为key和value,而Hashtable不可以)。

   HashMap没法保证映射的顺序一直不变,但是作为HashMap的子类LinkedHashMap,如果想要预知的顺序迭代(默认按照插入顺序),你可以很轻易的置换为HashMap,如果使用Hashtable就没那么容易了。

   HashMap不是同步的,而Hashtable是同步的。

   迭代HashMap采用快速失败机制,而Hashtable不是,所以这是设计的考虑点。

  6、在Hashtable上下文中同步是什么意思?

   同步意味着在一个时间点只能有一个线程可以修改哈希表,任何线程在执行hashtable的更新操作前需要获取对象锁,其他线程等待锁的释放。

  7、什么叫做快速失败特性

   从高级别层次来说快速失败是一个系统或软件对于其故障做出的响应。一个快速失败系统设计用来即时报告可能会导致失败的任何故障情况,它通常用来停止正常的操作而不是尝试继续做可能有缺陷的工作。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。如果一个iterator在集合对象上创建了,其它线程欲“结构化”的修改该集合对象,并发修改异常 (ConcurrentModificationException) 抛出。

  8、怎样使Hashmap同步?

   HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。

  9、什么时候使用Hashtable,什么时候使用HashMap

   基本的不同点是Hashtable同步HashMap不是的,所以无论什么时候有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。

  如果在将来有一种可能—你需要按顺序获得键值对的方案时,HashMap是一个很好的选择,因为有HashMap的一个子类 LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说HashMap更灵活。

  10、为什么Vector类认为是废弃的或者是非官方地不推荐使用?或者说为什么我们应该一直使用ArrayList而不是Vector

   你应该使用ArrayList而不是Vector是因为默认情况下你是非同步访问的,Vector同步了每个方法,你几乎从不要那样做,通常有想要同步的是整个操作序列。同步单个的操作也不安全(如果你迭代一个Vector,你还是要加锁,以避免其它线程在同一时刻改变集合).而且效率更慢。当然同样有锁的开销即使你不需要,这是个很糟糕的方法在默认情况下同步访问。你可以一直使用Collections.sychronizedList来装饰一个集合。

  事实上Vector结合了“可变数组”的集合和同步每个操作的实现。这是另外一个设计上的缺陷。Vector还有些遗留的方法在枚举和元素获取的方法,这些方法不同于List接口,如果这些方法在代码中程序员更趋向于想用它。尽管枚举速度更快,但是他们不能检查如果集合在迭代的时候修改了,这样将导致问题。尽管以上诸多原因,Oracle也从没宣称过要废弃Vector。



原创粉丝点击