java常用集合及其特点

Java提供的众多集合类由两大接口衍生而来:Collection接口和Map接口,以下只列出了常用的实现类

Collection接口定义了一个包含一批对象的集合。接口的主要方法包括:

  • size() - 集合内的对象数量
  • add(E)/addAll(Collection) - 向集合内添加单个/批量对象
  • remove(Object)/removeAll(Collection) - 从集合内删除单个/批量对象
  • contains(Object)/containsAll(Collection) - 判断集合中是否存在某个/某些对象
  • toArray() - 返回包含集合内所有对象的数组

Map接口在Collection的基础上,为其中的每个对象指定了一个key,并使用Entry保存每个key-value对,以实现通过key快速定位到对象(value)。Map接口的主要方法包括:

  • size() - 集合内的对象数量
  • put(K,V)/putAll(Map) - 向Map内添加单个/批量对象
  • get(K) - 返回Key对应的对象
  • remove(K) - 删除Key对应的对象
  • keySet() - 返回包含Map中所有key的Set
  • values() - 返回包含Map中所有value的Collection
  • entrySet() - 返回包含Map中所有key-value对的EntrySet
  • containsKey(K)/containsValue(V) - 判断Map中是否存在指定key/value

对于List接口:

ArrayList基于数组来实现集合的功能,其内部维护了一个可变长度的数组对象(数组默认长度为10,每次扩容默认为1.5倍原来的容量)

LinkedList基于双向链表来实现集合的功能,每个Node都拥有前一个Node和后一个的引用,要注意的是它的get方法会遍历整个链表,所以不要使用get方法遍历元素,应该使用iterator接口

Vector是一个线程安全的ArrayList但是他是通过加锁实现的,效率低,但是他的好处是可以定义数组长度的扩容因子,现在基本没人用了

CopyOnWriteArrayList是ArrayList的线程安全版本,与Vector不同,它通过写时复制的操作来解决线程安全问题,在写的时候,它会先复制出一个副本,在新副本上进行写的操作,然后再修改引用,CopyOnWriteArrayList只能保证数据的最终一致性,并不能保证实时一致性,并且它会占用更多的内存空间.

注意点:

写时复制不会修改原来的容器,只修改副本容器,所以可以对原始的容器进行并发的读,实现了读写分离,读的操作发生在原始容器上,写的操作发生在副本容器上

读操作的线程可能不会立即读取到新修改的数据,因为修改操作发生在副本上,但是最终修改操作会完成并且更新容器,因此这是最终一致性,因此它不适用与实时读的场景

COWA的add操作都是在锁的保护下进行的,这样做事为了避免在多线程并发add的时候复制出多个副本,而读的操作是不需要加锁的,因此它适用于读多写少的场景

对于Set接口:

Set 接口继承Collection,用于存储不含重复元素的集合。几乎所有的Set实现都是基于同类型Map的,简单地说,Set是阉割版的Map。每一个Set内都有一个同类型的Map实例(CopyOnWriteArraySet除外,它内置的是CopyOnWriteArrayList实例),Set把元素作为key存储在自己的Map实例中,value则是一个空的Object。Set的常用实现也包括 HashSet、TreeSet、ConcurrentSkipListSet等,原理和对应的Map实现完全一致。

对于Map接口:

HashMap:底层结构jdk1.8以前是使用数组+链表来实现的,jdk1.8以后是采用数组+链表+红黑树实现,在链表长度阈值超过8的时候,链表将转化为红黑树,小于6的时候又转回来,此外它是线程不安全的,支持null值为key,而且会把这个key放在数组的0号位置,HashMap的基础容量为16,默认的填充因子为0.75,其扩容时默认翻倍即(2*16*0.75).多线程情况下使用Collections.synchronizedMap()可以得到一个线程安全的HashMap

Hashtable:(已经很少使用)线程安全版本的HashMap,加锁来实现线程同步,不允许null值作为key,初始容量为11,负载因子为0.75,默认扩容时capacity*2+1

ConcurrentHashMap:HashMap的线程安全版本,使用分离锁和volatile等方法极大地提升了读写性能,同时也能保证在绝大部分情况下的数据一致性。但其不能保证绝对的数据一致性, 在一个线程向Map中加入Entry的操作没有完全完成之前,其他线程有可能读不到新加入的Entry

注意点:

jdk1.7以前ConcurrentHashMap本质上还是采用链表+数组的形式存储键值对的。但是,为了提高并发,把原来的整个 table 划分为 n 个 Segment 。所以,从整体来看,它是一个由 Segment 组成的数组。然后,每个 Segment 里边是由 HashEntry 组成的数组,每个 HashEntry之间又可以形成链表。我们可以把每个 Segment 看成是一个小的 HashMap,其内部结构和 HashMap 是一模一样的。

jdk1.8采用CAS+synchronized

jdk1.8中ConcurrentHashMap取消了分段式锁的封装,存储结构和数据操作原理与普通HashMap一样,数组+[链表|树]。其保证线程安全的核心思想是,插入元素时如果没有冲突,也就是说index处为空,则执行CAS插入操作;如果index处已经有元素了,则使用synchronized锁定index处元素,再进行插入操作。

LinkedHashMap:和HashMap非常类似,但它在Enrty的基础上增加了两个用于前插和后插的引用,来实现能够按照Enrty的插入顺序进行遍历

TreeMap:基于红黑树实现的Map结构,Enrty拥有左右叶子结点和父节点的引用,同时还记录了自己的颜色,TreeMap的Entry是有序的,所以提供了一系列方便的功能,比如获取以升序或降序排列的KeySet(EntrySet)、获取在指定key(Entry)之前/之后的key(Entry)等等

对于Queue/Deque接口:

Queue和Deque接口继承Collection接口,实现FIFO(先进先出)的集合。二者的区别在于,Queue只能在队尾入队,队头出队,而Deque接口则在队头和队尾都可以执行出/入队操作

Queue接口常用方法:

  • add(E)/offer(E):入队,即向队尾追加元素,二者的区别在于如果队列是有界的,add方法在队列已满的情况下会抛出IllegalStateException,而offer方法只会返回false
  • remove()/poll():出队,即从队头移除1个元素,二者的区别在于如果队列是空的,remove方法会抛出NoSuchElementException,而poll只会返回null
  • element()/peek():查看队头元素,二者的区别在于如果队列是空的,element方法会抛出NoSuchElementException,而peek只会返回null

Deque接口常用方法:

  • addFirst(E) / addLast(E) / offerFirst(E) / offerLast(E)
  • removeFirst() / removeLast() / pollFirst() / pollLast()
  • getFirst() / getLast() / peekFirst() / peekLast()
  • removeFirstOccurrence(Object) / removeLastOccurrence(Object)

ConcurrentLinkedQueue是基于链表实现的队列,队列中每个Node拥有到下一个Node的引用:由于Node类的成员都是volatile的,所以ConcurrentLinkedQueue自然是线程安全的。能够保证入队和出队操作的原子性和一致性,但在遍历和size()操作时只能保证数据的弱一致性。

LinkedBlocklingQueue是一种无界的阻塞队列。所谓阻塞队列,就是在入队时如果队列已满,线程会被阻塞,直到队列有空间供入队再返回;同时在出队时,如果队列已空,线程也会被阻塞,直到队列中有元素供出队时再返回。LinkedBlocklingQueue同样基于链表实现,其出队和入队操作都会使用ReentrantLock进行加锁。所以本身是线程安全的,但同样的,只能保证入队和出队操作的原子性和一致性,在遍历时只能保证数据的弱一致性。

ArrayBlockingQueue是一种有界的阻塞队列,基于数组实现。其同步阻塞机制的实现与LinkedBlocklingQueue基本一致,区别仅在于前者的生产和消费使用同一个锁,后者的生产和消费使用分离的两个锁。

SynchronousQueue不能保存任何元素,size永远是0,peek()永远返回null。向其中插入元素的线程会阻塞,直到有另一个线程将这个元素取走,反之从其中取元素的线程也会阻塞,直到有另一个线程插入元素。这种实现机制非常适合传递性的场景。也就是说如果生产者线程需要及时确认到自己生产的任务已经被消费者线程取走后才能执行后续逻辑的场景下,适合使用SynchronousQueue

开启一个线程的方法

继承Thread类,继承后重写run方法,调用对象的start方法开启线程

实现Runnable接口,实现run方法,将此对象放在Thread类构造器中,创建Thread类对象然后调用start方法

线程池+Callable方法

如何保证线程安全

synchronized关键字

reetrantlock锁

CAS+volatile

final关键字

修饰类表示类不可被继承,修饰方法表示方法不能被重写 ,修饰变量表示变量不可被更改

值得注意的一点是局部内部类和匿名内部类访问局部变量必须加上final关键字

内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就随着方法的执行完毕而销毁,当外部类的方法结束了,局部变量就被销毁了,但是内部类对象还是存在的(稍后GC再进行回收),这时内部类对象访问了一个不存在的变量,为了解决这个问题就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡之后,内部类依然可以访问它,实际访问的是局部变量的copy,这样就延长了局部变量的生命周期

将局部变量复制为内部类的成员变量的时候,必须保证这两个变量时一样的,也就是我们在内部类中修改了成员变量,方法中的局部变量也得跟着改,所以就将局部变量设置为final,对他初始化后就不让你去修改这个变量,这就保证了两个变量的一致性,这实际上也是一种妥协.

spring的模板和特点?

  • 方便解耦,简化开发,通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
  • AOP编程的支持,通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
  • 声明事物的支持,在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
  • 方便程序的测试,可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
  • 方便集成各种优秀框架,Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。

spring的核心是ioc(控制反转)+aop(面向切面编程)

常用的设计模式?--见设计模式专栏

redis的特点

redis是一种键值数据库但是他在保持键值数据库简单快捷的特点的同时又吸收了部分关系数据库的优点,它不仅保存Strings类型的数据,还能保存Lists类型(有序)和Sets类型(无序)的数据,而且还能完成排序(SORT) 等高级功能,在实现INCR,SETNX等功能的时候,保证了其操作的原子性,除此以外,还支持主从复制等功能.

速度快-->使用标准C写,所有数据都在内存中完成,读写速度分别达到10万/20万

持久化-->采用写时复制的技术,可以异步的保存在磁盘上,RDB+AOF

支持事务-->但是不保证原子性,redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

16.整理华为面经--1相关推荐

  1. 阿里P8亲自教你!熬夜整理华为最新Java笔试题

    前言 Mysql的锁机制确实非常重要,所以在这里做一个全面的总结整理,便于以后的查阅,也分享给大家. Mysql的锁机制还是有点难理解的,所以这篇文章采用图文结合的方式讲解难点,帮助大家理解,讲解的主 ...

  2. 华为云空间联系人是不是机主_电脑上整理华为云空间联系人数据

    新建联系人: 登录华为云空间官网,进入"联系人"后,点击搜索栏上方 "新建联系人"图标,输入联系人相关信息(姓名.手机.工作单位.电子邮箱等),点击" ...

  3. 整理 华为AP-3010DN_V2配置创建wifi

    华为AP-3010DN_V2配置创建wifi 首先将光猫来的网线插在 华为无线接入点PoE口上,因为华为AP默认的管理IP是169.254.1.1,所以要在使用wifi无线上网的电脑上,修改网卡IP为 ...

  4. 刚从阿里、头条面试回来,熬夜整理华为最新Java笔试题,进阶学习

    开头 我们面试的时候 ,经常会被问这种到问题:Spring中bean的循环依赖怎么解决? Spring中bean的加载过程? spring相关的问题一直是大厂面试常问到的一个问题,也是一直困扰这我们, ...

  5. 吐血整理华为MateBookD Win10+940MX显卡下 安装NVIDIA控制面板、CUDA、CuDNN、Anaconda环境GPU版本tensorflow2.0

    2021/01/08 声明,不建议使用CUDA10.0,因为对pytorch.torch_geometric很难找到对应版本的(反正CUDA10.0下我失败了).本篇依然可以为一些NVIDA设置错误提 ...

  6. 01-步骤整理-华为海思Hikey970开发板的AOSP编译烧写

    最近结合第三方厂家与官方提供的编译文档,实践整理了Hikey970单板编译与烧写Google原生AOSP(Android Open Source Project)系统的步骤. 单板参数:6GB LPD ...

  7. Servlet(一,熬夜整理华为最新Java笔试题

    5.再次访问服务器时,客户端请求中就携带着之前保存的Cookie中保存的值,服务器就根据Cookie就能够知道客户端的身份是什么了. 在HttpServletRequest中也可以获取到Cookie的 ...

  8. 鸿蒙商务旅行箱,全军出击!华为智选发布16款新品:鸿蒙分布式技术来了

    原标题:全军出击!华为智选发布16款新品:鸿蒙分布式技术来了 近日,华为智选品鉴会在深圳举行,这也是华为智选在今年举办的首个专场品鉴会. "给全场景智慧生活添点温度",华为与生态合 ...

  9. 鸿蒙见面会为什么没选在深圳,全军出击!华为智选发布16款新品:鸿蒙分布式技术来了近日,华...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 全军出击!华为智选发布16款新品:鸿蒙分布式技术来了 近日,华为智选品鉴会在深圳举行,这也是华为智选在今年举办的首个专场品鉴会. "给全场景智慧 ...

最新文章

  1. ICCV2021论文全汇总!附下载链接
  2. 中国首个海底数据中心样机测试数据揭晓,达世界先进能效水平
  3. 多态及其内部原理剖析
  4. MySQL管理员指南
  5. js高级技巧之柯里化
  6. 11.* 指针 引用
  7. 2017.4.16 阶乘之和 思考记录
  8. python笔记03_IO编程
  9. java的poi技术读取Excel[2003-2007,2010]
  10. 相对于其他框架的离子应用开发:它被炒作了吗?
  11. Linux Namespace机制简介
  12. Go语言实现大数开方程序
  13. completable java_java8 CompletableFuture异步编程
  14. 一个元素的偏移的方法
  15. C/C++编程:仿函数
  16. uvaoj 10066 - The Twin Towers 最长公共子序列(LCS)
  17. 协调才暴力-精英乒乓论坛
  18. 如何防止条码流水号打印出现重码漏码错码的防呆检错系统?
  19. GPIO(通用输入/输出接口)
  20. 2019年,会不会是我这一辈子的人生巅峰?

热门文章

  1. elementUI radio选中样式修改为勾勾
  2. 基于Python的《玛丽冒险》小游戏
  3. 天猫国际刘鹏:永远在做别人做不到的事
  4. 在线HTTP请求头响应头转JSON工具
  5. 什么是SDK?什么是API?
  6. Spectral normalization及torch实现
  7. 什么是挂载?mount的用处在哪?(适合新手,讲解的非常好)
  8. 索尼3D 虚拟社区 PlayStation Home,完美PK Second Life
  9. 微信小程序的蓝牙使用
  10. centos上开启6379端口