一些常用对象的区别(更新中)

来源:互联网 发布:苹果手机变成3g网络了 编辑:程序博客网 时间:2024/05/23 10:51

一、ArrayList和LinkedList区别:(一个移动元素,一个移动指针)

对于集合类的ArrayList,能确定大小的就确定下来,经过测试,确定大小的速度比不确定大小的速度快,因为ArrayList里添加数据会自动扩充ArrayList的大小,会消耗时间和空间,列表扩充是成倍扩充的,所以可能比原来的要大甚至大很多空间。

例子:

  long _start = System.currentTimeMillis();    ArrayList<String> list = new ArrayList<String>( 1000000 );    System.out.println(runtime.freeMemory() );    for ( int i = 0; i< 1000000; i++ ) {       list.add( new String("test list speed") );    }    long _end = System.currentTimeMillis();    System.out.println( ( _end- _start ) / 1000.0 );

1.ArrayList是基于动态数组的数据结构,LinkedList基于双向循环链表的数据结构。共同点是有顺序,元素可以重复。普通的存放和访问数据,存放在ArrayList中即可。链表的指针也是占用空间的。

2.对于随机访问以及在末尾添加或删除元素不涉及数据移动,ArrayList优于LinkedList,因为LinkedList要移动指针。

3.对于指定位置的新增和删除操作,即涉及中间元素的增加和删除LinedList比较占优势,因为ArrayList要移动数据,移动元素操作比指针操作消耗多。LinkedList是链表结构,所以不能确定初始化大小。

4.Vector底层也是基于动态数组,是线程安全的,占用更多的系统开销。

实际例子:

比如将一个大容量数据暂存在一个容器中便于之后的访问,使用ArrayList比较合适。

比如说数据库连接池相当于在头部删除,在尾部增加的,涉及增删操作比较频繁,所以适合使用LinkedList。

 

二、synchronizedMap和ConcurrentHashMap区别:

 ConcurrentHashMap  提供了较好的并发解决方案,它的思想比hashTable 和synchronizedMap更高明一些,允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

ConcurrentHashMap不允许有null的键和值。


三、String/StringBuffer/StringBuilder区别:

String类是不可变类,在每次对String类型进行改变的时候其实都等同于生成了一个新的 String对象,然后将指针指向新的String对象。

病例:

String Str = "abc";

for( int i = 0; i < 10000; i++)  {  

   Str + = "def";  

}  

    如果这样的话,这个 for 循环完毕后,如果内存中的对象没有被 GC 清理掉的话,内存中一共有上万个了,再如果这是一个很多人使用的系统,数目吓人了。

在JVM解释时:

①   String str = "This is only a" + " simple" + " test.";  

即是:

String str = "This is only a simple test.";

而:

String str1 = "This is only a";

String str2 = "simple ";

String str3=  "test.";

② String str4 = str1 + str2 + str3;

这时候str4效率就没有①来的高了 ,而且还开辟了几个不同的引用内存。

 

使用StringBuffer,StringBuilder类则结果就不一样了,每次结果都是对对象本身进行操作,而不是生成新的对象,再改变对象引用。

StringBuffer线程安全,StringBuilder线程不安全,但是速度快。

StringBuilder一般使用在方法内部来完成类似"+"功能,因为是线程不安全的,所以用完以后可以丢弃.StringBuffer用在全局变量中。

 

四、HashMap、HashTable、HashSet区别:

Hashtable类   
Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。

Hashtable通过initial   capacity和load   factor两个参数调整性能。通常缺省的load   factor   0.75较好地实现了时间和空间的均衡。增大load   factor可以节省空间但相应的查找时间将增大,这会影响像get和put这样的操作。 

HashMap类   
HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null,即null   value和null   key。,但是将HashMap视为Collection时(values()方法可返回Collection),其迭代子操作时间开销和HashMap的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load   factor过低。   

HashSet类 
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
原创粉丝点击