集合中的线程初体验

java零基础入门-高级特性篇(四)  HashSet 和 Collections

本章继续讲集合,先来看看Set集合。Set集合的特点,1:无序,2:无重复。上一章讲了HashMap,最后提到HashSet的底层实现其实就是HashMap。那么为什么用HashMap就可以实现无序和不重复,下面看看具体如何使用HashMap实现HashSet。

hashset和hashmap的区别

hashset底层用hashmap实现,那为什么不直接用hashmap就完了,非要整个hashset出来?

集合

如果有这个问题,可以回头看看前面讲的集合框架的设计。设计hashset是用来保存那种不需要使用下标操作元素,并且不能重复的集合。set集合的元素和List集合的元素一样,都是一个对象。而hashmap的元素是key-value键值对,因为数据存储类型不同,所以需要将set和map区分开来。看一下图,帮助回忆一下。

hashmap如何实现hashset

Set集合最重要的一个方法就是add(E e),如何往一个Set集合添加元素,了解了添加元素的原理,查找元素理解起来就简单许多。hashset的add方法,用的就是是hashmap的put方法。下面是源代码:

map.put(e,PRESENT) == null

这里需要重点理解的是,一个对象如何存入一个key-value。从上面这句代码中,可以发现,在往set集合添加元素的时候,这个元素被用来当做map的key,而value是一个常量。

为什么直接将对象作为key呢?因为hashmap使用哈希算法对key进行计算,计算后的结果就是底层数组的位置,所以当使用hashset的时候,需要对放进set的对象进行哈希计算,至于value,hashset不关心。

hashmap的key的特性就是不会重复,后添加相同的数据会将前一个数据覆盖掉。正好满足了set集合不重复的特性,所以直接用hashmap即可以满足hashset集合的要求。


关系

其实这里容易绕晕的是几个底层实现的结构,这里用一个图来说明一下。HashSet利用HashMap的Key的特性来实现,而HashMap是利用数组和链表的特性来实现,这样应该明白这几个结构之间的关系了吧。

这次hashset真的讲完了。

Collections工具

使用集合存放数据的时候,会有很多情况要对集合进行操作。特别是List集合,因为List集合的有序性,会需要按照特定的顺序操作集合,而java也专门提供了Collections工具来对集合进行操作。下面来看看几个例子

List list = new ArrayList();

list.add("one");//此处省略 ,一共添加五个元素one,two,three,fore,five

Collections方法

Collection.reverse(list);//反转集合元素的顺序

Collection.shuffle(list);//随机顺序,多次随机结果可能不一样

Collection.sort(list);//升序排序,先数字后字母,数字0-9,字母A-Z a-z的顺序,逐位比较

Collection.swap(list,0,3);//交换第一个和第四个元素位置

看一个swap的源码实现

Object tmp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

嗯,完了,是不是有一种这玩意我都会写,干嘛要用这个的感觉?其实确实可以自己写,但是一般提供工具给别人用,肯定要提供全套,再就是合理的使用工具会减少不必要的代码,提升代码的可读性。

Collection 和 Collections

这两个长得很像,但是作用差别很大,初学者切勿将两者概念混淆。Collection是集合体系中的上层接口,而Collections是操作集合的工具。何谓工具?还记不记得我们讲的静态方法?不记得的快去复习类和对象的文章。

Collections作为一个工具类,里面提供的方法都是静态方法,所以在上面的例子中,都是直接使用类Collections来调用方法,Collections提供了大量的静态方法来操作集合,有没有加深对静态成员这个概念的理解?

用Collections工具类创建线程安全的集合

上次讲vector的时候,说了他是线程安全的集合,而List是线程不安全的。但是可以通过一些方法让List变成线程安全的,所以vector目前已经没有使用的必要了。那么如何让List变成线程安全的集合呢?答案就是使用Collections工具可以将List变为线程安全。

Collections有一系列的synchronized方法来使集合变为线程安全的,一系列是指不仅仅可以将List变为线程安全的,Set,Map也有方法变成线程安全的。

List list = Collections.synchronizedList(new ArrayList());

Set set = Collections.synchronizedSet(new HashSet());

Map map = Collections.synchronizedMap(new HashMap());

使用以上三个工具方法就可以将普通集合变为线程安全的集合。这些方法有什么魔法么,为什么外面包一层就线程安全了?下面来简单介绍一下多线程以及使用多线程会遇到的问题。

多线程是什么?

多线程就是并行处理问题。比如去银行取钱,如果只有一个取款机队伍就会排很长,但是如果有多个取款机同时办理业务,速度就会快很多。这就是多线程的思路,多个线程(取款机)处理一个问题(取钱)。

多个ATM

为什么多线程有安全问题?

假设现在有2个人要取款,如果2个人同时操作一个取款机会发生什么?第一个人密码输了3位数,第二个人跑来按3位数,第一个人删了准备重新输,又被第二个人按了3下,这样下去两个人都别想取钱。多个线程抢同一个资源就会产生线程安全问题,实际开发中遇到的线程安全问题会比这种情况还要复杂。

怎么解决?

带锁的ATM

新款取款机,带门带锁的!一旦一个人进去了,先锁门,然后就可以放心大胆的取钱了,这时候没有人会来跟你抢着取钱了。代码里面也是可以上锁的,所以线程安全的集合都是带有锁机制的。

高效并发容器

这里是补充知识,了解即可。其实上面的这几个方法确实可以将普通集合转为线程安全的集合,但是实现很粗糙,导致效率不是很高。所以就有了专门为并发情况设计的更加高效的并发容器,比如CopyOnWriteArrayList,CopyOnWriteArraySet,ConcurrentHashMap。

上锁也是有很多种上锁的方法,继续取钱的例子。

最极端粗暴的上锁方式就是,银行每次只准进一个人,这样绝对不会有任何问题,绝对安全,银行所有保安都盯着你,你还能玩出花来?但是这样做效率极端底下。比如老版本的vector和hashtable就是用类似这种粗暴的方法来上锁。

再来看稍微先进点的上锁方式。就是银行可以进很多人,但是办理不同业务的分开来,取钱的一个队,存钱的一个队,办理财换密码再来一个队,每个队同时只能一个人办,办的人进小房间,上锁。这种上锁的粒度比上面那种要小,效率要快很多。

最后就是最先进的锁了。也就是类似并发容器这种,升级版的取款机不仅可以取钱还可以存钱,还能办其他业务~也就是说不管办什么业务,找个人最少的队排着就行了,所有机器可以同时办相同或者不同的业务。这种锁的粒度最小,只对操作对象的数据进行上锁,效率最高。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容

  • Java集合类可用于存储数量不等的对象,并可以实现常用的数据结构如栈,队列等,Java集合还可以用于保存具有映射关...
    小徐andorid阅读 1,898评论 0 13
  • 原文地址 Java集合 Java集合框架:是一种工具类,就像是一个容器可以存储任意数量的具有共同属性的对象。 Ja...
    gyl_coder阅读 971评论 0 8
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX阅读 861评论 0 1
  • 在一个方法内部定义的变量都存储在栈中,当这个函数运行结束后,其对应的栈就会被回收,此时,在其方法体中定义的变量将不...
    Y了个J阅读 4,406评论 1 14
  • 周末陪娃上课外班的时候,谈谈妈一边晒儿子的绘画作品,一边吐槽对学校教育的不满: 你们不知道,现在私立小学一年级就开...
    职场二宝妈频道阅读 456评论 0 0