Java中Map和Set集合,LinkedHashSet和LinkedHashMap集合无序和有序的区别

Map、Set集合存放是无序的,然而LinkedHashSet和LinkedHashMap等集合却有序,请解释这是什么原因?

有序和无序:这里的有序和无序不是指集合中的排序,而是是否按照元素添加的顺序来存储对象。

Map:

Map是无序的,它的存储结构是哈希表<key,value>键值对,map中插入元素是根据key计算出的哈希值来存储元素的,因此他不是按照元素的添加顺序来存储对象的,所以Map是无序的。它的实现类有:HashMap、TableMap和TreeMap。

其中LinkedHashMap是有序的,hashMap用来保证存储的值键值对,list用来保证插入的顺序和存储的顺序一致。

LinkedHashMap:

HashMap和双向链表合二为一即是LinkedHashMap。所谓LinkedHashMap,其落脚点在HashMap,因此更准确地说,它是一个将所有Entry节点链入一个双向链表的HashMap。由于LinkedHashMap是HashMap的子类,所以LinkedHashMap自然会拥有HashMap的所有特性。比如,LinkedHashMap的元素存取过程基本与HashMap基本类似,只是在细节实现上稍有不同。当然,这是由LinkedHashMap本身的特性所决定的,因为它额外维护了一个双向链表用于保持迭代顺序。

它相当于是在HashMap中插入了一个双向链表,然后每次插入的数据按照插入的顺序来进行排序,它相当于定义了一个双向链表,来把所有的Entry串联起来。并不保存Key和Value

LinkedHashMap增加了时间和空间上的开销,但是它通过维护一个额外的双向链表保证了迭代顺序。特别地,该迭代顺序可以是插入顺序,也可以是访问顺序。

LinkedHashMap相对于HashMap,增加了双链表的结果(即节点中增加了前后指针),其他处理逻辑与HashMap一致。

Set:

Set是无序的,并且set中的元素不能重复。set的底层实现其实是Map,它是计算key的哈希值来确定元素在数组中的存放位置,所以是无序的,应为在Map中key的值不能重复,所以set中的元素不能重复。它的实现类有:haseSet、TreeSet。

LinkedHashSet:

LinkedHashSet集合也是根据元素hashCode值来决定元素存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。也就是说,当遍历LinkedHashSet集合里元素时,HashSet将会按元素的添加顺序来访问集合里的元素。

LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。

LinkedHashSet是Set集合的一个实现,具有set集合不重复的特点,同时具有可预测的迭代顺序,LinkedHashSet包含两个参数:初始化容量和载入属性。

对于LinkedHashSet而言,它继承与HashSet、又基于LinkedHashMap来实现的。LinkedHashSet底层使LinkedHashMap来保存所有元素,它继承与HashSet,其所有的方法操作上又与HashSet相同,因此LinkedHashSet 的实现上非常简单,只提供了四个构造方法,并通过传递一个标识参数,调用父类的构造器,底层构造一个LinkedHashMap来实现,在相关操作上与父类HashSet的操作相同,直接调用父类HashSet的方法即可。 对于LinkedHashSet而言,它继承与HashSet、又基于 LinkedHashMap来实现的。

LinkedHashSet是具有可预知迭代顺序的Set接口的哈希表和链接列表实现。此实现与HashSet的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。

LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但和HashSet不同的是,它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。

双向链表:

双向链表是链表的一种,它的每个数据节点都有两个指针分别指向直接后继和直接前驱,所以从双向链表的任意一个节点开始都可以很方便的访问它的前驱节点和后继节点。这是双向链表的优点,缺点是每个节点都需要保存当前节点的next和prev两个属性,这样才能保证优点。所以需要更多的内存开销,并且删除和添加也会比较费时间。

下图是双向链表的节点:
prve指向上一个结点,next指向下一个结点

多个节点相互连接,保证了数据录入的顺序。

 

 

____________________________________________________________________________________________________

 
 

Map集合:

Map用于保存具有映射关系的数据,总是以键值对的方式存储数据。Map集合的key和value都可以是任何引用类型的数据。Map集合的key不允许重复,value允许重复。key和value之间存在单向一对一关系,即通过指定的键可以找到唯一,确定的value。Map集合中获取数据时,只要给出指定的key,就可以取出对应的value。

 

 Hashtable是java一开始发布时就提供的键值映射的数据结构,而HashMap产生于JDK1.2。虽然Hashtable比HashMap出现的早一些,但是现在Hashtable基本上已经被弃用了。而HashMap已经成为应用最为广泛的一种数据类型了。造成这样的原因一方面是因为Hashtable是线程安全的,效率比较低。
 

HashMap和Hashtable实现类

HashMap和Hashtable都是Map接口的典型实现类,Hashtable是一个古老的集合,JDK1.0起就出现了。

HashMap和Hashtable的典型区别:

(1)Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现。所以HashMap比Hashtable的性能高一点。

(2)Hashtable不允许使用null作为key和value。

Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注释中有说明 。

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
 

注意:HashMap和Hashtable判断两个key相等的标准是:两个key通过equals方法比较返回true,两个key的hashCode值也要相等。
HashMap和Hashtable包含一个containsValue方法用于判断是否包含指定vlaue,HashMap和Hashtable判断值相等的标准:只要两个对象通过equals方法比较返回true即可。

 

(1)java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。

 Collection   
├List   
│├LinkedList   
│├ArrayList   
│└Vector   
│ └Stack   
└Set 

(2)java.util.Collections 是一个包装类(工具类/帮助类)。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。
代码示例:

import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
  
public class TestCollections { 
      
    public static void main(String args[]) { 
        //注意List是实现Collection接口的 
        List list = new ArrayList(); 
        double array[] = { 112, 111, 23, 456, 231 }; 
        for (int i = 0; i < array.length; i++) { 
            list.add(new Double(array[i])); 
        } 
        Collections.sort(list); 
        for (int i = 0; i < array.length; i++) { 
            System.out.println(list.get(i)); 
        } 
        // 结果:23.0 111.0 112.0 231.0 456.0 
    } 
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值