Java 中常用集合性能比较


List 集合:

List: 有顺序的,元素可以重复 
遍历:for 迭代 
排序:Comparable Comparator Collections.sort() 
ArrayList:底层用数组实现的List 
特点:查询效率高,增删效率低 轻量级 线程不安全 
遍历:
		ArrayList<String> al=new ArrayList();
		al.add("winsun");   al.add("weixin");   al.add("mybole");
		for(int i=0;i<al.size();i++)
		{
			System.out.println(al.get(i));
		}//for遍历
		Iterator it=al.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next());
		}//迭代器遍历
LinkedList:底层用双向循环链表 实现的List 
特点:查询效率低,增删效率高 
Vector: 底层用数组实现List接口的另一个类 
特点:重量级,占据更多的系统开销 线程安全
ArrayList,LinkedList,Vestor这三个类都实现了java.util.List接口,但它们有各自不同的特性,主要如下:

一、同步性

ArrayList,LinkedList是不同步的,而Vestor是的。所以如果要求线程安全的话,可以使用ArrayList或LinkedList,可以节省为同步而耗费开销。但在多线程的情况下,有时候就不得不使用Vector了。当然,也可以通过一些办法包装ArrayList,LinkedList,使他们也达到同步,但效率可能会有所降低。

二、数据增长
从内部实现机制来讲ArrayList和Vector都是使用Objec的数组形式来存储的。当你向这两种类型中增加元素的时候,如果元素的数目超出了内部数组目前的长度它们都需要扩展内部数组的长度,Vector缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因为你可以通过设置集合的初始化大小来避免不必要的资源开销。

三、检索、插入、删除对象的效率

ArrayList和Vector中,从指定的位置(用index)检索一个对象,或在集合的末尾插入、删除一个对象的时间是一样的,可表示为O(1)。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i),其中n代表集合中元素的个数,i代表元素增加或移除元素的索引位置。为什么会这样呢?以为在进行上述操作的时候集合中第i和第i个元素之后的所有元素都要执行(n-i)个对象的位移操作。
LinkedList中,在插入、删除集合中任何位置的元素所花费的时间都是一样的—O(1),但它在索引一个元素的时候比较慢,为O(i),其中i是索引的位置。

所以,如果只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是对其它指定位置的插入、删除操作,最好选择LinkedList

HashMap和Hashtable及HashSet的区别


Hashtable类   
    Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。   
    添加数据使用put(key,   value),取出数据使用get(key),这两个基本操作的时间开销为常数。   
  Hashtable通过initial   capacity和load   factor两个参数调整性能。通常缺省的load   factor   0.75较好地实现了时间和空间的均衡。增大load   factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。   
  使用Hashtable的简单示例如下,将1,2,3放到Hashtable中,他们的key分别是”one”,”two”,”three”:   
      Hashtable   numbers   =   new   Hashtable();   
      numbers.put(“one”,   new   Integer(1));   
      numbers.put(“two”,   new   Integer(2));   
      numbers.put(“three”,   new   Integer(3));   
    要取出一个数,比如2,用相应的key:   
      Integer   n   =   (Integer)numbers.get(“two”);   
      System.out.println(“two   =   ”   +   n);   
    由于作为key的对象将通过计算其散列函数来确定与之对应的value的位置,因此任何作为key的对象都必须实现hashCode和equals方法。hashCode和equals方法继承自根类Object,如果你用自定义的类当作key的话,要相当小心,按照散列函数的定义,如果两个对象相同,即obj1.equals(obj2)=true,则它们的hashCode必须相同,但如果两个对象不同,则它们的hashCode不一定不同,如果两个不同对象的hashCode相同,这种现象称为冲突,冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode()方法,能加快哈希表的操作。   
    如果相同的对象有不同的hashCode,对哈希表的操作会出现意想不到的结果(期待的get方法返回null),要避免这种问题,只需要牢记一条:要同时复写equals方法和hashCode方法,而不要只写其中一个。   
    Hashtable是同步的。   
    
  HashMap类   
    HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null   value和null   key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load   factor过低。   
    
  WeakHashMap类   
    WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。 



HashSet请参考对Set的描述   
    
          Set是一种不包含重复的元素的Collection,即任意的两个元素e1和e2都有e1.equals(e2)=false,Set最多有一个null元素。   
    Set的构造函数有一个约束条件,传入的Collection参数不能包含重复的元素。  请注意:必须小心操作可变对象(Mutable   Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
两个通用Set实现是HashSet   和TreeSet。要决定用哪一个,那是非常简单明了的。   HashSet   要快得多   (对大多数操作是常数时间之于对数时间(constant   time   vs.   log   time)),   但不提供排序保证。如果你需要使用   SortedSet   中的操作,或者按顺序迭代对你来说是重要的,那么请使用   TreeSet。   否则,使用   HashSet。   在大多数时间都不使用   HashSet   ,对你来说是个公平的赌博。     
    
    关于   HashSet,有一件事应该牢记,即就条目数和容量之和来讲,迭代是线性的。因此,如果迭代性能很重要,那就应该慎重选择一个适当的初始容量。容量选得太大,既浪费空间,也浪费时间。   默认的初试容量是101,   一般来讲,它比你所需要的要多。可以使用   int   构造函数来指定初始容量。要分配   HashSet   的初始容量为17:     
    
  Set   s=   new   HashSet(17);     
    
    HashSets   另有一个称作   装载因数(load   factor)   的"调整参数(tuning   parameter)"   。如果你非常在乎你的   HashSet   的空间的使用,请阅读   HashSet   文本以获取详细信息。否则,就使用默认值吧。如果你接受默认装载因数,但你确实又想指定初始容量,那么,选一个大约是你期望你的   Set   将增长到的容量的两倍的数。如果你的猜测不着边,它也可以增长,或只是浪费一点空间。但都没有大问题。如果你知道有关正确尺寸的一个最佳值,用它吧;如果不知道,那就使用一个旧的值,或使用一个偶数值。它真的不是非常重要。这些事情只能使   HashSet   稍稍变好一点点。     
    
    TreeSet   没有调整参数。除   clone   之外,HashSet   和   TreeSet   都仅有那些由它们各自的接口所要求的操作   (Set   和   TreeSet),而没有任何别的操作。     
  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java常用集合的一些答案: 1. ArrayList(动态数组):ArrayList是Java常用集合之一,它可以根据需要自动调整大小。它实现了List接口,并且可以存储任意类型的对象。你可以使用add()方法向ArrayList添加元素,使用get()方法获取指定位置的元素,使用size()方法获取ArrayList的大小等。 2. LinkedList(链表):LinkedList是另一种常用集合,它实现了List接口和Deque接口。与ArrayList不同,LinkedList使用链表来存储元素,因此在插入和删除元素时具有更好的性能。你可以使用add()方法向LinkedList添加元素,使用get()方法获取指定位置的元素,使用remove()方法删除指定位置的元素等。 3. HashSet(哈希集合):HashSet是一个不允许包含重复元素的集合。它实现了Set接口,并且使用哈希表来存储元素。你可以使用add()方法向HashSet添加元素,使用contains()方法检查元素是否存在,使用remove()方法删除元素等。 4. HashMap(哈希映射):HashMap是一个键值对的集合,它实现了Map接口。它使用哈希表来存储键值对,其键是唯一的。你可以使用put()方法向HashMap添加键值对,使用get()方法获取指定键的值,使用containsKey()方法检查键是否存在等。 5. TreeSet(树集合):TreeSet是一个有序的集合,它实现了SortedSet接口。它使用红黑树来存储元素,并且保证元素按照升序排列。你可以使用add()方法向TreeSet添加元素,使用first()方法获取第一个元素,使用last()方法获取最后一个元素等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值