JavaSE_4_集合
1、Map和ConcurrentHashMap的区别?
Map和ConcurrentHashMap的区别,Map是接口,ConcurrentHashMap是实现类
2、hashMap内部具体如何实现的?
HashMap基于哈希思想,实现对数据的读写,底层采用数组+链表实现,可以存储null键和null值,线程不安全:
- 当我们往HashMap中put元素时,先根据key的hashCode重新计算hash值,然后根据得到的hash值通过hash&(tab.length–1)计算出对应的数组下标,如果数组该位置上已经存放有其他元素了,那么新元素将以链表的形式按照头插法存入链表,如果数组该位置上没有元素,就直接将新元素放到此数组中的该位置上,当存储的链表长度大于8时会将链表转换为红黑树;(hash方法根据key的hashCode重新计算一次散列,该算法加入了高位计算,防止低位不变,高位变化时,造成的hash冲突)
- 当我们从HashMap中get元素时,先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素;
- 当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,所以为了提高查询的效率,就要对HashMap的数组进行扩容,当HashMap中元素个数超过(数组大小*加载因子)时,就会进行数组扩容,数组大小默认值为16,加载因子默认值为0.75,把数组的大小扩展为原来的2倍,然后重新计算每个元素在数组中的位置,这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设数组的合适长度能够有效的提高HashMap的性能。
3、如果HashMap的key是一个自定义的类,怎么办?
要重写equals方法和hashcode方法,以保证equals相等的对象其hashcode一定也相等。
4、ArrayList和LinkedList的区别,如果一直在list的尾部添加元素,用哪个效率高
ArrayList底层时数组实现的,LinkedList底层是双向链表实现的,ArrayList执行修改和查找的效率比较高,LinkedList执行增加和删除的效率比较高。
如果一直在list尾部增加元素,ArrayList效率更高,但是如果需要在指定位置添加元素时,LinkedList效率更高。
5、请你解释HashMap的容量为什么是2的n次幂?
- HashMap默认大小为16,又是以原大小的2倍进行扩容,所以默认情况下,HashMap的容量总是2的n次幂;
- 如果HashMap初始化大小不是2的n次幂也会自动将传入容量转换为2的n次幂,因为计算HashMap下标的求余操作(hash%length)效率不高,源码中优化成了与操作(hash&(length-1)),但是这两个操作能等价的前提是length为2的n次幂。
6、HashMap中为什么有可能产生死循环?
在单线程情况下,只有一个线程对HashMap的数据结构进行操作,是不可能产生闭合回路的,只有在多线程并发的情况下才会出现这种情况;那就是在put操作的时候,如果size>Capacity*loadFactor,那么这时候HashMap就会进行rehash操作,随之HashMap的结构就会发生翻天覆地的变化,很有可能存在两个线程在这个时候同时触发了rehash操作,产生闭合回路。
下图为单线程下的扩容过程:
下图为两个线程并发下的扩容过程(无死循环):
下图为两个线程并发下的扩容过程(有死循环):
7、ConcurrentHashMap锁加在了哪些地方?
- JDK1.7中,ConcurrentHashMap采用分段锁机制,实现并发的更新操作,底层采用数组+链表的存储结构;将数组分成若干(默认16)个segment,每个segment的容量默认为16,segment继承了ReentrantLock,表明每个segment都可以当做一个锁,这样对于每个segment中的数据需要同步操作时,都是使用每个segment容器对象自身的锁来实现的,只有对全局需要改变时才锁定所有的segment(比如计算size)。
- JDK1.8中,ConcurrentHashMap抛弃了segment分段锁机制,利用CAS+Synchronized来保证并发更新的安全,底层采用数组+链表+红黑树的存储结构。
8、TreeMap底层,红黑树原理?
9、concurrenthashmap有啥优势,1.7,1.8区别?
底层采用分段数组+链表实现,线程安全;通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是volatile的,能保证读取到最新的值;写操作加锁。);ConcurrentHashMap允许多个修改操作并发进行。
在JDK1.7版本中,ConcurrentHashMap的数据结构是由一个Segment数组和多个HashEntry组成,Segment数组分割成多个小的table来进行加锁,也就是锁分离技术,而每一个Segment元素存储的是HashEntry数组+链表。
在JDK1.8版本中,摒弃了Segment的概念,而是使用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS来操作。
10、ArrayList是否会越界?
可能会越界,在多线程操作同一个ArrayList的时候,由于ArrayList的add()方法没有同步锁,所以多线程调用这个方法的时候,可能存在多个线程拿到相同的size值去判断需要的容量(size+1)是否大于ArrayList的容量,而执行到 elemntData[size++] = e 时却是有序的,这时,由于ensureCapacityInternal()没有适当的扩大ArrayList的容量,从而导致插入数据的长度大于ArrayList的剩余容量,于是也就抛出了越界的异常。
11、什么是TreeMap?
12、ConcurrentHashMap的原理是什么?
ConcurrentHashMap使用锁分段技术,将数据分成一段一段的存储,给每一段数据配置一把锁,当一个线程占用锁访问其中一段数据时,其他段的数据也能被其它线程访问。
ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成;Segment是一种ReentrantLock,HashEntry用于存储键值对数据,一个ConcurrentHashMap里包含一个Segment数组,Segment的结构与HashMap类似,是一种链表散列数据结构,一个 Segment包含一个HashEntry数组,每个HashEntry是一个链表结构的元素,每个Segment维护着一个HashEntry数组里的元素,当要对HashEntry的数据进行修改时,就必须先获得对应的Segement锁。
13、Java集合类框架的基本接口有哪些?
总共有两大接口:Collection和Map,一个元素集合,一个是键值对集合;其中List和Set接口继承了Collection接口,一个是有序元素集合,一个是无序元素集合;而ArrayList和LinkedList实现了List接口,HashSet实现了Set接口,这几个都比较常用;HashMap和HashTable实现了Map接口,并且HashTable是线程安全的,但是HashMap性能更好。
14、为什么集合类没有实现Cloneable和Serializable接口?
克隆或者是序列化的语义和含义是跟具体的实现相关的;因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。
15、什么是迭代器?
可迭代是Java集合框架下所有集合类的一种共性,也就是把集合中的所有元素遍历一遍。
迭代器(Iterator)模式,又叫游标模式,它的含义是,提供一种方法访问一个容器对象中各个元素,而又不需要暴露该对象的内部细节;简单的说,迭代器就是一个接口,实现了该接口的类就叫做可迭代类,这些类多数时候指的就是java.util包下的集合类;java通过提供Iterator和Iterable俩个接口来实现集合类的可迭代性,迭代器主要的用法是:首先用hasNext()方法作为循环条件,再用next()方法得到每一个元素,最后在进行相关的操作。
16、Iterator和ListIterator的区别是什么?
List和Set都能通过iterator()来取得其迭代器;对List来说,也可以通过ListIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面:
- ListIterator有add()方法,可以向List中添加对象,而Iterator不可以;
- ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历,而Iterator不可以;
- ListIterator可以定位当前的索引位置,通过nextIndex()和previousIndex()实现,而Iterator不可以;
- 都可实现删除对象,但是ListIterator可以实现对象的修改,通过set()方法实现,而Iierator仅能遍历,不能修改。
17、快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
快速失败:在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception;
- 原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量,集合在被遍历期间如果内容发生变化,就会改变modCount的值,每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历,否则抛出异常,终止遍历;
- 注意:这里异常的抛出条件是检测到 modCount != expectedmodCount 这个条件,如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出,因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug;
- 场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。
安全失败:采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历;
- 原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception;
- 缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的;
- 场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
18、HashMap和Hashtable有什么区别?
- HashMap继承于AbstractMap抽象类,Hashtable继承于Dictionary字典,实现Map接口
- HashMap是非线程安全的,HashTable是线程安全的(通过synchronized实现);
- HashMap的键和值都允许有null值存在,而HashTable则不行;
- 因为线程安全的问题,HashMap效率比HashTable的要高;
- HashMap适合于单线程环境,而Hashtable适合于多线程环境。
- HashTable是遗留类
- 多线程环境下有同步的ConcurrentHashMap替代
19、ArrayList,Vector,LinkedList的存储性能和特性是什么?
- ArrayList和Vector都是使用数组方式存储数据,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素的移动等内存操作,所以索引数据快而插入数据慢;
- Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,Vector属于遗留容器,已经不推荐使用,但是由于ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另一个类的构造器中创建新的对象来增强实现);
- LinkedList使用双向链表实现存储,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
20、Collection 和 Collections的区别。
- java.util.Collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,Collection接口在Java 类库中有很多具体的实现,Collection接口的意义是为各种具体的集合提供最大化的统一操作方式,其直接继承接口有List与Set;
- java.util.Collections是一个包装类,它包含各种有关集合操作的静态方法,此类不能实例化,就像一个工具类,用于对集合中元素进行排序、搜索以及线程安全等各种操作,服务于Java的Collection框架。
21、你所知道的集合类都有哪些?主要方法?
Collection接口:
Collection是最基本的集合接口,一个Collection代表一组Object,Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的子接口,如List和Set,所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素,后一个构造函数允许用户复制一个Collection,Collection支持一个iterator()的方法,该方法返回一个迭代器,使用该迭代器即可逐一访问Collection中的每一个元素;
List接口:
List是有序的Collection,可以使用索引来访问List中的元素,类似于Java的数组,List允许存放相同的元素,除了具有Collection接口必备的iterator()方法外,List还提供一个ListIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator允许添加,删除,设定元素,还能向前或向后遍历,实现List接口的常用类有LinkedList,ArrayList,Vector和Stack;
LinkedList类:
LinkedList实现了List接口,允许null元素,LinkedList主要提供了增加、删除、修改、查找等方法,LinkedList没有同步方法,如果多个线程同时访问一个List,必须自己实现访问同步,一种解决方法是在创建List时构造一个同步的List【List list = Collections.synchronizedList(new LinkedList(...))】;
ArrayList类:
ArrayList实现了可变大小的数组,允许null元素,ArrayList主要提供了增加、删除、修改、查找等方法,每个ArrayList实例都有一个容量(Capacity),这个容量可随着不断添加新元素而自动增加,当需要插入大量元素时,在插入前通过调用ensureCapacity方法来增加ArrayList的容量,和LinkedList一样,ArrayList也是非同步的;
Vector类:
Vector类似ArrayList,但是Vector是同步的,由Vector创建的Iterator,和ArrayList创建的Iterator是同一接口,但是因为Vector是同步的,当一个Iterator被创建而且正在被使用时,另一个线程改变Vector的状态,这时调用Iterator的方法将抛出异常;
Stack 类:
Stack继承自Vector,实现了一个后进先出的堆栈,Stack提供了基本的push和pop方法,以及peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置,Stack刚创建后是空栈;
Set接口:
Set是一种不包含重复元素的Collection,Set最多有一个null元素,传入的Collection参数不能包含重复的元素;
Map接口:
Map提供key到value的映射,一个Map中不能包含相同的key,每个key只能映射一个value;
Hashtable类:
Hashtable继承Map接口,实现了一个key-value映射的哈希表,任何非空(non-null)的对象都可作为key或value,添加数据使用put(key, value),取出数据使用get(key),要同时重写equals方法和hashCode方法,Hashtable是同步的;
HashMap类:
HashMap和Hashtable类似,不同之处在于HashMap是非同步的,并且允许null元素;
WeakHashMap类:
WeakHashMap是一种改进的HashMap,它对key实行弱引用,如果一个key不再被外部所引用,那么该key可以被GC回收。
22、List、Set、Map是否继承自Collection接口?
List和Set继承了Collection接口,Map没有继承Collection接口。
23、List、Map、Set三个接口存取元素时,各有什么特点?
存放时:
- List以特定的索引来存放元素(有顺序的存放),可以有重复的元素;
- Set存放元素是无序的,而且不可重复;
- Map保存键值对的映射,映射关系可以是一对一或者多对一,需要注意的是,键无序不可重复,值可重复;
取出时:
- List取出元素可通过for循环,foreach循环和Iterator迭代器迭代;
- Set取出元素可通过foreach循环,Iterator迭代器迭代;
- Map取出元素需要转换为keySet或者entrySet,然后进行Iterator迭代器迭代或者foreach循环。
et 和List 都继承了Conllection
JavaSE_4_集合的更多相关文章
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- .Net多线程编程—并发集合
并发集合 1 为什么使用并发集合? 原因主要有以下几点: System.Collections和System.Collections.Generic名称空间中所提供的经典列表.集合和数组都不是线程安全 ...
- 一起学 Java(三) 集合框架、数据结构、泛型
一.Java 集合框架 集合框架是一个用来代表和操纵集合的统一架构.所有的集合框架都包含如下内容: 接口:是代表集合的抽象数据类型.接口允许集合独立操纵其代表的细节.在面向对象的语言,接口通常形成一个 ...
- 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)
建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...
- java基础_集合List与Set接口
List接口继承了Collection的方法 当然也有自己特有的方法向指定位置添加元素 add(索引,添加的元素); 移除指定索引的元素 remove(索引) 修改指定索引的元素 set ...
- Java基础Collection集合
1.Collection是所有集合的父类,在JDK1.5之后又加入了Iterable超级类(可以不用了解) 2.学习集合从Collection开始,所有集合都继承了他的方法 集合结构如图:
- 轻量级“集合”迭代器-Generator
Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Generator的改进之前,我们先通过一个简单却显而易见的例子来了解下G ...
- Asp.net MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合
今天为大家分享下 Asp.net MVC 将数据从前台传递到后台的几种方式. 环境:VS2013,MVC5.0框架 1.基本数据类型 我们常见有传递 int, string, bool, double ...
- 这些.NET开源项目你知道吗?.NET平台开源文档与报表处理组件集合(三)
在前2篇文章这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧 和这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,大伙热情高涨.再次拿出自己的私货,在.NET平台 ...
随机推荐
- 关于request的几个字段值
domain: localhost host: localhost:9000 url: /wechat/mynews action: WechatController.myNews path: /we ...
- [xdoj1158]阶乘求逆元(常用于求组合数)
http://acm.xidian.edu.cn/problem.php?id=1158 解题关键:此题注意将$\sum\limits_{i = 0}^x {C_x^iC_y^{i + k}}$转化为 ...
- 实现hadoop中的机架感知
hadoop中声明是有机架感知的功能,能够提高hadoop的性能.平时我们使用的hadoop集群,实际上是从来没有使用上这个功能的. hadoop中所说的 机架感知的实现实际上这样的: hadoop启 ...
- 9、IPA通路分析相关网页教程
IPA FAQ: http://ingenuity.force.com/ipa/IPATutorials# ####有各种相关教程和帮助文件. IPA 分析结果展示: http://www.lucid ...
- 使用GEO数据库来筛选差异表达基因,KOBAS进行KEGG注释分析
前言 本文主要演示GEO数据库的一些工具,使用的数据是2015年在Nature Communications上发表的文章Regulation of autophagy and the ubiquiti ...
- python包管理
如果是python 项目目录,例如pycharm里新建的python项目,则可以通过from,import导入目录下的文件夹. 如果是普通文件目录,则代码里不能相对方式导入该目录下的文件夹,需要加入要 ...
- URAL 1297 Palindrome (后缀数组+RMQ)
题意:给定一个字符串,求一个最长的回回文子串,多解输出第一个. 析:把字符串翻转然后放到后面去,中间用另一个字符隔开,然后枚举每一个回文串的的位置,对第 i 个位置,那么对应着第二个串的最长公共前缀, ...
- Docker 企业级镜像仓库 Harbor 的搭建与维护
目录 一.什么是 Harbor 二.Harbor 安装 2.1.Harbor 安装环境 2.2.Harbor安装 2.3 配置HTTPS 三.Harbor 的使用 3.1.登录Harbor并使用 3. ...
- 转:基础篇|PHP如何解决网站大流量和高并发
基础篇 高并发架构基础概念和优化思路 高并发架构相关概念 并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程 ...
- Wannafly summer camp Day2I(思维)
#include<bits/stdc++.h>using namespace std;int a[1000007],b[1000007],c[1000007];int find_max(i ...