关于集合:JAVA-集合

1、List,Set都是继承自Collection接口,Map则不是 2、List特点:元素有放入程序,元素可反复 ,Set特点:元素无放入程序,元素不可反复,反复元素会笼罩掉,(留神:元素尽管无放入程序,然而元素在set中的地位是有该元素的HashCode决定的,其地位其实是固定的,退出Set 的Object必须定义equals()办法 ,另外list反对for循环,也就是通过下标来遍历,也能够用迭代器,然而set只能用迭代,因为他无序,无奈用下标来获得想要的值。) 3.Set和List比照: Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素地位扭转。 List:和数组相似,List能够动静增长 查找元素效率高,插入删除元素效率低,因为会引起其余元素地位扭转。4.Map适宜贮存键值对的数据 5.线程平安汇合类与非线程平安汇合类 LinkedList、ArrayList、HashSet是非线程平安的,Vector是线程平安的;HashMap是非线程平安的,HashTable是线程平安的;StringBuilder是非线程平安的,StringBuffer是线程平安的。

February 27, 2023 · 1 min · jiezi

关于集合:Java-集合有哪些内容

明天咱们就来简略的理解下java中的汇合,有理解过得敌人都晓得,也都用过,比如说做罕用的List,还有Set、Map,而且像List和Set都是用于存储单列数据的汇合,他们的父接口都是Conllection,List的特点是存储的值是有序且容许反复的,Set的特点是存储的元素是惟一、不可反复且无序的,而Map的特点则是用于存储双列数据的汇合,存储的数据时无序的,键不能够反复,值能够反复。 接下来咱们就把它们拆出来具体的来聊一聊。 List接口(通常有些面试官会问这样一个比拟根底的问题:List是接口还是类?大家感觉呢,有教训的小伙伴必定一下子就能答复进去,然而有一些刚开始学习的小白同学可能会有一些犹豫哦,那这次我都会给大家说说滴,小白同学看完当前有人再问你这样的问题就不会再犹豫啦) 首先咱们要明确:咱们java中的汇合分为单列汇合和双列汇合,单列汇合的顶级接口是:Conllection,双列汇合的顶级接口是:Map 而List就是属于单列汇合Conllection的子接口,List接口的实现类如下:(所以List是接口不是类哦,通过上面能够多理解理解List接口的实现类都有哪些): 1.ArrayList(List接口的实现类):底层数据结构是数组,查问快,增删慢,因为家喻户晓ArrayList的底层数据结构是数组,向ArrayList中退出元素add的时候,有可能会导致List的扩容, 因为ArrayList底层是数组构造,但数组不反对动静扩容,所以ArrayList的扩容机制就是再创立一个新数组,把就数组数据迁徙到新数组,而后再退出新元素,这样一个过程下来也就是造成ArrayList减少元素慢的外围起因了。 而ArrayList在删除元素时底层是将删除索引地位起到最初索引地位完结中所有的元素,一一向前复制一个索引地位,再将最初索引地位元素设置为null,简略来说就是,假如我当初要删除这个汇合中0索引地位上的元素,我将0索引地位下面的元素删除之后,并不是将这个地位的元素间接设置为null,而是前面1索引地位到最初索引地位上的所有元素都要走一个一一向前复制一个索引地位过程,直到最初一个索引元素向前复制完结之后,将开端地位上空缺的元素复制为null,所以也就是说在删除元素的时候会影响其余索引地位上的元素的地位,所以也会升高删除元素的效率。 (ArrayList汇合删除元素之后其余索引地位上的元素挪动地位的变动过程)了解完增删慢的起因,其实查问快的起因大家就曾经很好了解了,ArrayList在查问元素时底层是通过拜访数组元素形式进行查问。数组(Array)是一种线性表(线性表就是数据排成像一条线一样的构造。每个线性表上的数据最多只有前和后两个方向)数据结构。 它用一组间断的内存空间,来存储一组具备雷同类型的数据。并且申明一个数组时,会在内存中申请一块间断相邻的内存空间。当要通过索引拜访数组元素时,可通过数组地址值和偏移量,间接计算出要查找元素的内存地址,所以数组反对通过索引间接拜访元素,效率十分高。数组中的元素都是有下标的,所以依据下标就能够很快的找到你要查问的元素了(应用get()办法, 就能够间接取的是数组对应下标中的值)。 2.LinkedList(List接口的实现类):底层数据结构是链表,查问慢,增删快 LinkedList之所以查问慢是因为,LinkedList底层是一个链表, 链表必定没有下标的概念,所以他不能像ArrayList一样,应用get()办法, 就能够间接取的是数组对应下标中的值,它只能是对总数遍历,而后取循环下标的值,所以如果LinkedList链表size越大,那么会使for循环的次数增多导致遍历的工夫也会越长,查问也就慢了(然而如果大家在编码过程中还是须要思考应用LinkedList的话在查问的时候能够应用getFirst()、getLast() 办法缩小for循环的次数来绝对减少查问的速度)。 而LinkedList之所以减少元素时快次要是因为,LinkedList 应用add(E e)间接增加元素或者add(int index, E e)指定地位增加元素,这两种办法插入元素,绝对与ArrayList效率是较高的,因为ArrayList减少元素的时候可能须要扩容和元素的拷贝,减少了开销,而LinkedList 是断开指定地位的链接把新节点增加进来即可,所以整个增加过程中,零碎也只做了两件事件,增加一个新的节点,而后保留该节点和前节点的援用关系,简略来说就是新减少了一个链接而已,所以效率高。 删除元素的时候也是依据remove(Object o) 删除元素或者remove(int index)删除指定地位元素这两种办法进行元素的删除,所以简略来说删除效率高次要是因为只须要删除某个链接,再链接新的元素即可,不须要批改列表中残余的元素。 3.Vector(List接口的实现类):底层数据结构是数组,正因为它的底层是数组所以他的特点跟ArrayList一样是查问快,增删慢的特点,这一点能够参考下面ArrayList的解释。Set接口也是单列汇合Conllection的子接口,接下来咱们就持续看看他的实现类有哪些吧! 1.HashSet(Set接口的实现类):底层数据结构是哈希表,它是基于 HashMap 实现的,底层采纳 HashMap 来保留元素,HashSet就是为了进步查问效率的,意思就是在查问某个值是否存在的时候,ArrayList须要遍历能力获取到某个值的地位,而HashSet能够通过HashCode疾速进行定位,而且HashSet是依据哈希算法来进行对象的存取的,存取速度很快,当HashSet中元素的个数超出数组本来的大小,就会进行扩容,而哈希表其实次要依赖hashcode()和equals()这两个办法。简略来讲就是首先通过hashcode()来判断hashcode值是否雷同,如果雷同的话就会执行equals()来查看他们的返回值是否雷同,如果返回true的话,就阐明这两个元素反复,则不进行增加,如果返回是false的话,就间接增加到汇合当中。如果hashcode值不雷同就能够间接增加到汇合当中,以上就是针对于HashSet的特点的简略介绍。 2.LinkedHashSet(Set接口的实现类):底层数据结构是链表+哈希表,由链表保障元素的有序,由哈希表保障元素的惟一,LinkedHashSet是一个基于LinkedHashMap实现的有序去重汇合列表,LinkedHashSet中的元素没有反复;LinkedHashSet中的元素有程序,保护了增加程序;LInkedHashSet能够存储null值;这个容器不晓得大家在平时的工作用的多吗,反正我基本上没有用过,所以就是就是我集体针对于他的特点做的简略介绍。 3.TreeSet(Set接口的实现类):底层数据结构是红黑树,特点是元素惟一,且有序,由天然排序和比拟器排序来保障有序的特点,依据返回值是否是0来判断元素是否惟一。TreeSet是有序的Set汇合,因而反对add、remove、get等办法,TreeSet不反对疾速随机遍历,只能通过迭代器进行遍历,如果想把自定义类的对象存入TreeSet进行排序, 那么必须实现Comparable接口,或者实现一个比拟器,在类上implements Comparable,重写compareTo()办法,在办法内定义比拟算法, 依据大小关系, 返回负数正数或零,在应用TreeSet存储对象的时候, add()办法外部就会主动调用compareTo()办法进行比拟, 依据比拟后果应用二叉树模式进行存储。 简略写了一个排序大家能够粗鲁看看 这是排序的一个运行后果图,遍历两次是因为应用了两种不同的遍历形式接下来就该说说双列汇合Map了,大家能够看看他的实现类有哪些。 1.HashMap(Map接口的实现类):底层数据结构是数组+链表,基于哈希表的 Map 接口的实现。并容许应用 null 值和 null 键,是以 key-value 存储模式存在,每一个键值对也叫做一个Entry,依据键的hashCode值存储数据,大多数状况下能够间接定位到它的值,键key为null的记录至少只容许呈现一条,值value为null的记录能够有多条,HashMap 的实现不是同步的,这意味着它不是线程平安的,HashMap是由数组+链表+红黑树(JDK1.8后减少了红黑树局部,链表长度超过阈值(8)时会将链表转换为红黑树)实现的。对于HashMap常常会有面试官问HashSet和HashMap的区别?其实针对于这个问题,大家通过上述HashSet的解释也能总结进去了, 相同点: 1.都是采纳的Hash散列算法调配的数据, 2.都是线程不平安的, 3.数据查问是无序的; 不同点: 1.继承的父类不同 2.set的单键,而hashmap是能够存键值对 ...

December 27, 2022 · 1 min · jiezi

关于集合:利用共享内存实现比-NCCL-更快的集合通信

作者:曹彬 | 旷视 MegEngine 架构师 简介从 2080Ti 这一代显卡开始,所有的民用游戏卡都勾销了 P2P copy,导致训练速度显著的变慢。针对这种状况下的单机多卡训练,MegEngine 中实现了更快的汇合通信算法,对多个不同的网络训练绝对于 NCCL 有 3% 到 10% 的减速成果。 MegEngine v1.5 版本,能够手动切换汇合通信后端为 shm(默认是 nccl),只须要改一个参数。(因为 shm 模式对 CPU 有额定的占用,且只有在特定卡下能力提高效率,因而并没有默认关上) gm = GradManager()gm.attach(model.parameters(), callbacks=[dist.make_allreduce_cb("sum", backend="shm")])目前只实现了单机版本,多机暂不反对背景在大规模训练中,数据并行是最简略最常见的训练形式,每张卡运行齐全一样的网络结构,而后加上参数同步就能够了。 对于 数据并行的参数同步,目前有两种罕用的办法,Parameter Server 和 Gradient AllReduce: Parameter Server 计划须要额定机器作为参数服务器来更新参数,而且核心式的通信形式对带宽的压力很大,减少训练机器的同时通信量也线性减少;而 AllReduce 计划只是参加训练的机器之间相互同步参数,不须要额定的机器,可扩展性好。MegEngine 目前也是应用 AllReduce 计划作为数据并行的参数同步计划。而在 AllReduce 计划中,大家目前罕用的是 NCCL,Nvidia 自家写的 GPU 汇合通信库,通信效率很高。 看到这里,能够失去一个论断,数据并行的状况,用 NCCL 通信库能达到不错的成果。 到这里就完结了?当然不是,在 2080Ti 8 卡训练的状况下,在多个网络下,咱们绝对 NCCL 有 3% 到 10% 的性能晋升。(以 2080Ti 为例子是因为游戏卡不反对 P2P 通信,相对来说通信较慢,通信工夫长,节俭通信工夫能取得的收益较大) 这是怎么做到的呢,咱们一步一步来剖析(以下数据都是用 megengine.utils.profiler 导出,相干文档在 profiler文档)。 ...

August 9, 2021 · 2 min · jiezi

关于集合:7-集合

2.maplinkedHashMap在hashMap上减少一条双向链表,使hashMap构造放弃键值对插入程序,并实现了按程序拜访treeMap 红黑树(自均衡的排序二叉树) 一 list3.arraylistarraylist线程不平安,底层数组,反对快速访问,尾部有空余空间在尾减少删除工夫复杂度都是O(1),在指定地位减少删除工夫复杂度是O(n),因为要一个一个挪 vector线程平安,底层数组 4.linkedlist线程不平安底层双向链表(1.6以前循环链表),双向链表是由两个单向链形成的,双向循环链表是由两个单向环形成的不反对快速访问在头尾减少删除工夫复杂度是O(1),在指定地位减少删除工夫复杂度是O(n),因为要一个一个找到地位每个元素要存前驱和后继元素的地位 5.RandomAccess 接口标识此类是否有疾速定位拜访的能力,arraylist有,linkedlist没有 二 set7.hashSethashSet 线程不平安,能够存null,基于hashmap实现 linkedHashSetlinkedHashSet 能够按增加程序遍历,基于linkedHashMap实现 TreeSettreeSet能够按增加程序遍历,能够天然排序或定制排序,基于红黑树 三 map8 hashTable线程平安,因为外部办法根本都通过synchronized润饰根本淘汰,且kv都不能为null否则会npe初始大小11,扩容为2n+1,如果给出初始,会用你给的jdk1.8前 数组+链表 拉链法解决抵触 jdk1.8后 链表长度大于阈值(默认为8)时将链表转化为红黑树缩小搜寻工夫(转成红黑树前会判断,如果数组长度小于64会先扩容)② Hashtable(同一把锁) :应用 synchronized 来保障线程平安,效率十分低下。当一个线程拜访同步办法时,其余线程也拜访同步办法,可能会进入阻塞或轮询状态,如应用 put 增加元素,另一个线程不能应用 put 增加元素,也不能应用 get,竞争会越来越强烈效率越低。 hashMap非线程平安,通过 (n - 1) & hash 判断以后元素寄存的地位,初始大小16,扩容为2的幂次(求地位的时候速度快),如果给出初始,会用比你给的略微大一点的2的幂次多线程操作导致死循环问题次要起因在于并发下的 Rehash 会造成元素之间会造成一个循环链表。 treemap相比于HashMap来说 TreeMap 次要多了对汇合中的元素依据键排序的能力以及对汇合内元素的搜寻的能力。 相等hashCode()的默认行为是对堆上的对象产生独特值。即便两个对象的数据相等,因为是两个对象,他们的hash也不会相等。根本对象 == 是比拟值,援用对象、包装对象是比拟地址 ConcurrentHashMapJDK1.7 的 ConcurrentHashMap 底层采纳 分段的数组+链表 实现,JDK1.8 采纳的数据结构跟 HashMap1.8 的构造一样,数组+链表/红黑二叉树。实现线程平安的形式(重要): 在 JDK1.7 的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了宰割分段(Segment),每一把锁只锁容器其中一部分数据,多线程拜访容器里不同数据段的数据,就不会存在锁竞争,进步并发访问率。 到了 JDK1.8 的时候曾经摒弃了 Segment 的概念,而是间接用 Node 数组+链表+红黑树的数据结构来实现,并发管制应用 synchronized 和 CAS 来操作。(JDK1.6 当前 对 synchronized 锁做了很多优化) 整个看起来就像是优化过且线程平安的 HashMap,尽管在 JDK1.8 中还能看到 Segment 的数据结构,然而曾经简化了属性,只是为了兼容旧版本; ...

June 7, 2021 · 1 min · jiezi