集合总结

这篇博客详细介绍了Java集合框架中的HashMap、Hashtable、HashSet、ArrayList、LinkedList、Stack和Vector的区别及特性。讨论了线程安全问题,包括HashMap在多线程环境下的不安全性,以及Hashtable的效率问题。文章还提到了分段锁的概念,解释了ConcurrentHashMap如何通过锁分段技术实现线程安全。此外,还探讨了为什么在自定义类作为HashMap的key时需要重写hashCode()和equals()方法。最后,对比了HashSet、TreeSet和LinkedHashSet的区别,并简要概述了ArrayList的扩容机制。
摘要由CSDN通过智能技术生成

1)常见的集合有哪些

  • Collection接口的子接口包括:Set接口(唯一)和List接口(有序)

  • Map接口的实现类主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等

  • Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等

  • List接口的实现类主要有:ArrayList、LinkedList、Stack以及Vector等

    HashMap和HashTable以及ConcurrentHashMap的区别:

    Hashtable

    数组+链表实现,key,value都不能为null,线程安全,实现方式是修改数据时锁住整个HashTable,效率低。
    初始大小11,扩容*2+1。

    HashMap

    数组+链表实现,key,value都可以为null,线程不安全。
    初始大小16,扩容*2。

    TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。效率不如HashMap,Map需要有序的场合才使用TreeMap。

    ConcurrentHashMap

    分段数组+链表实现,线程安全。用分离锁实现,允许多个修改操作并发。跨段修改时按顺序锁定所有段,再按顺序释放。

    Properties 继承于 Hashtable ,来表示一个持久的属性集。一个唯一和IO流相结合的集合。

    基本的存储方法 :setProperty(String key, String value)

    ​ getProperty(String key)

    ​ 与流相关的方法

    Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储

    • void store(OutputStream out, String comments)
    • void store(Writer writer, String comments)

HashMap线程不安全

因为多线程环境下,使用Hashmap进行put操作可能会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。例如如下代码:

final HashMap<String, String> map = new HashMap<String, String>(2);
for (int i = 0; i < 10000; i++) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            map.put(UUID.randomUUID().toString(), "");
        }
    }).start();
}

Hashtable线程安全但效率低下

Hashtable容器使用synchronized来保证线程安全但在线程竞争激烈的情况下Hashtable的效率非常低下。因为当一个线程访问Hashtable的同步方法时,其他线程访问Hashtable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。

分段锁

HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术

HashMap为什么要重写hashCode()和equals()方法

hashMap中,如果key为自定义类,那么就必须要重写hashCode()和equals()方法

在put方法中,判断key是否相等,用的是equals方法。其实get方法中也是一样。那么默认的equals方法就不一定能满足我们的要求了。因此要重写equals方法。

涉及到Object.hashCode()的通用约定了:

  1. 每次应用执行期间,在对象做equals比较所用到的信息没有修改之前,hashcode方法的返回值应该是相同的。
  2. 两个对象equals方法相同,那么hashCode值必须相同;
  3. 两个对象equals方法不同,那么hashCode值不一定不同。

如果只重写equals方法,不重写hashCode方法,那么显然会违反第二条约定

HashSet,TreeSet和LinkedHashSet的区别

总体而言,如果你需要一个访问快速的Set,你应该使用HashSet;当你需要一个排序的Set,你应该使用TreeSet;当你需要记录下插入时的顺序时,你应该使用LinedHashSet。

Set接口:线程都不安全

**1.**Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false。

2.Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说,只要两个对象用equals方法比较返回true,Set就不会接受这两个对象。

​ |——SortedSet接口——TreeSet实现类

Set接口——|——HashSet实现类

​ |——LinkedHashSet实现类

HashSet

1.不能保证元素的排列顺序,顺序有可能发生变化

  1. 不是同步的 内部的数据结构是哈希表,是线程不安全的。

  2. 集合元素可以是null,但只能放入一个null

    HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相等

TreeSet:(TreeSet是二叉树实现的)

TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式ÿ

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值