面试(02)————Java基础和集合

一、Java基础知识

1、面向对象的特征

 2、Java 的基本数据类型有哪些

3、JDK JRE JVM 的区别

4、重载和重写的区别

5、Java中==和equals的区别 

6 、String、StringBuffer、StringBuilder三者之间的区别

7、接口和抽象类的区别是什么?

8、反射

 9、jdk1.8 的新特性(高薪常问)

9.1、Lambda 表达式

 9.2、方法引用

9.3、函数式接口

 9.4、接口允许定义默认方法和静态方法

 9.5、Stream API

 9.6、日期/时间类改进

9.7、Optional 类  

9.8、Java8 Base64 实现

10、Java 的异常

 11、BIO、NIO、AIO 有什么区别?(高薪常问)

 12、Threadloal 的原理(高薪常问)

13、同步锁、死锁、乐观锁、悲观锁 (高薪常问) 

14、说一下 synchronized 底层实现原理?(高薪常问) 

 15、synchronized 和 volatile 的区别是什么?(高薪常问)

 16、synchronized 和 Lock 有什么区别? (高薪常问)

 二、集合

1、常见的数据结构

2、集合和数组的区别 

 3、List 和 Map、Set 的区别

4、 List 和 Map、Set 的实现类 

4.1、Connection 接口

4.2、Map 接口有四个实现类 

5、Hashmap 的底层原理 

6、Hashmap 和 hashtable ConcurrentHashMap 区别 


 

一、Java基础知识

1、面向对象的特征

面向对象的特征:封装、继承、多态、抽象。
封装:封装是将数据和操作(方法)捆绑在一起的机制,使得对象的内部细节对外部是隐藏的,外部只能通过对象的公共接口来访问和操作对象。封装提供了信息隐藏和保护数据的功能,使得对象的使用更加简单和安全。
继承:继承是一种机制,允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以重用父类的代码,并且可以在此基础上扩展或修改功能。通过继承,可以实现代码的重用性和扩展性,减少代码的重复编写。
多态:多态是指相同的操作或方法在不同的对象上可以有不同的行为。在面向对象编程中,多态可以通过继承和方法重写来实现。多态提高了代码的灵活性和可扩展性,使得程序可以根据实际情况选择合适的行为。
抽象:抽象是指将复杂的现实世界映射到程序设计中的简化模型,只关注对象的重要特征和行为,忽略不必要的细节。抽象可以通过类和接口来实现,在面向对象编程中,通过抽象可以隐藏对象的复杂性,提高程序的可理解性和可维护性。

 2、Java 的基本数据类型有哪些

91373c13562f40f7bef0573924cf1695.png

3、JDK JRE JVM 的区别

5f04e0755ceb42b48e3ee2140f803cc9.png

JDK(Java Development Kit)是整个Java 的核心,是java开发工具包,包括了Java 运行环境JRE、Java 工具和Java 基础类库。
 
JRE(Java Runtime Environment)是运行JAVA 程序所必须的环境的集合,包含java虚拟机和java程序的一些核心类库。
 
JVM 是Java Virtual Machine(Java 虚拟机)的缩写,是整个java 实现跨平台的最核心的部分,能够运行以Java 语言写作的软件程序。

4、重载和重写的区别

 重载:发生在同一个类中,方法名必须相同,参数类型不同.个数不同.顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。

 

重写:发生在父子类中,方法名.参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能重写该方法。

5、Java中==和equals的区别 

== 的作用:
        
基本数据类型,== 比较的是值是否相等

        引用类型(对象),== 比较的是引用地址是否相同

equals 的作用 :
        引用类型:默认情况下,比较的是地址值。
        特:String、Integer、Date这些类库中equals被重写,比较的是内容而不是地址!



请解释字符串比较之中“ == ”和equals() 的区别?
答:==:比较的是两个字符串内存地址(堆内存)的数值是否相等,属于数值比较;                   equals():比较的是两个字符串的内容,属于内容比较。

6 、String、StringBuffer、StringBuilder三者之间的区别

 String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)


String 中的String 类中使用final 关键字修饰字符数组来保存字符串,private final char value[] ,String对象是不可变的,也就可以理解为常量,线程安全。

AbstractStringBuilder 是StringBuilder 与StringBuffer 的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf 等公共方法。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。

StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

总结:

(1)如果要操作少量的数据用String;
(2)多线程操作字符串缓冲区下操作大量数据用StringBuffer;
(3)单线程操作字符串缓冲区下操作大量数据用StringBuilder。

7、接口和抽象类的区别是什么?

实现:抽象类的子类使用extends 来继承;接口必须使用implements 来实现接口。

构造函数:抽象类可以有构造函数;接口不能有。
main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。
实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符

8、反射

在 Java 中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和
方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息 以及动
态调用对象方法的功能成为 Java 语言的反射机制。
获取 Class 对象的 3 种方法 :
调用某个对象的 getClass()方法
Person p=new Person();
Class clazz=p.getClass();
调用某个类的 class 属性来获取该类对应的 Class 对象
Class clazz=Person.class;
使用 Class 类中的 forName()静态方法(最安全/性能最好)
Class clazz=Class.forName("类的全路径"); (最常用)

 9、jdk1.8 的新特性(高薪常问)

9.1、Lambda 表达式

Lambda 允许把函数作为一个方法的参数。

d722e8baf4884c07978f01742b02fa84.png

 9.2、方法引用

方法引用允许直接引用已有 Java 类或对象的方法或构造方法
7729c1fdf2df4d0a9ebbf69ea2f745b4.png

上例中我们将 System.out::println 方法作为静态方法来引用。  

9.3、函数式接口

有且仅有一个抽象方法的接口叫做函数式接口,函数式接口可以被隐式转换为 Lambda 表
达式。通常函数式接口上会添加@FunctionalInterface 注解。

 9.4、接口允许定义默认方法和静态方法

 从 JDK8 开始,允许接口中存在一个或多个默认非抽象方法和静态方法

 9.5、Stream API

新添加的 Stream API(java.util.stream)把真正的函数式编程风格引入到 Java 中。这种
风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理, 比如筛选,排序,聚合等。
f726b1677cfa4ca69d0bdf9922578489.png

 9.6、日期/时间类改进

之前的 JDK 自带的日期处理类非常不方便,我们处理的时候经常是使用的第三方工具包,
比如 commons-lang 包等。不过 JDK8 出现之后这个改观了很多,比如日期时间的创建、
比较、调整、格式化、时间间隔等。
这些类都在 java.time 包下,LocalDate/LocalTime/LocalDateTime

9.7、Optional 类  

Optional 类是一个可以为 null 的容器对象。如果值存在则 isPresent()方法会返回 true,
调用 get()方法会返回该对象。
d5d4d4e71f524317888020b6715484f8.png
762465e7dc0b45e6aa5b3c9a39f69a0b.png

9.8、Java8 Base64 实现

Java 8 内置了 Base64 编码的编码器和解码器。 

10、Java 的异常

6733c141da9640a48af9e4f1e654a6be.png

Throwable 是所有 Java 程序中错误处理的父类,有两种资类:Error 和 Exception。
Error:表示由 JVM 所侦测到的无法预期的错误,由于这是属于 JVM 层次的严重错误,导
致 JVM 无法继续执行,因此,这是不可捕捉到的,无法采取任何恢复的操作,顶多只能显
示错误信息。
Exception:表示可恢复的例外,这是可捕捉到的。
1.运行时异常:都是 RuntimeException 类及其子类异常,如 NullPointerException(空指
针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序
中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从
逻辑角度尽可能避免这类异常的发生。运行时异常的特点是 Java 编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用 try-catch 语句捕获它,也没有用 throws
子句声明抛出它,也会编译通过。
2.非运行时异常(编译异常)
:是 RuntimeException 以外的异常,类型上都属于 Exception
类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。
如 IOException、SQLException 等以及用户自定义的 Exception 异常,一般情况下不自定
义检查异常。
常见的 RunTime 异常几种如下
NullPointerException - 空指针引用异常
ClassCastException - 类型强制转换异常。
IllegalArgumentException - 传递非法参数异常。
ArithmeticException - 算术运算异常
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
IndexOutOfBoundsException - 下标越界异常
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
NumberFormatException - 数字格式异常
SecurityException - 安全异常
UnsupportedOperationException - 不支持的操作异常

 11、BIO、NIO、AIO 有什么区别?(高薪常问)

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用
方便,并发处理能力低。
 
NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通
道)通讯,实现了多路复用。
 
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO
的操作基于事件和回调机制。

 12、Threadloal 的原理(高薪常问)

 

ThreadLocal:为共享变量在每个线程中创建一个副本,每个线程都可以访问自己内部的副
本变量。通过 threadlocal 保证线程的安全性。
 
其实在 ThreadLocal 类中有一个静态内部类 ThreadLocalMap(其类似于 Map),用键值对
的形式存储每一个线程的变量副本,ThreadLocalMap 中元素的 key 为当前 ThreadLocal
对象,而 value 对应线程的变量副本。
 
ThreadLocal 本身并不存储值,它只是作为一个 key 保存到 ThreadLocalMap 中,但是
这里要注意的是它作为一个 key 用的是弱引用,因为没有强引用链, 弱引用在 GC 的时候可
能会被回收。这样就会在 ThreadLocalMap 中存在一些 key 为 null 的键值对(Entry)。因
为 key 变成 null 了,我们是没法访问这些 Entry 的,但是这些 Entry 本身是不会被清除的。
如果没有手动删除对应 key 就会导致这块内存即不会回收也无法访问,也就是 内存泄漏。使用完 ThreadLocal 之后,记得调用 remove 方法。 在不使用线程池的前提下,即使不调
用 remove 方法,线程的"变量副本"也会被 gc 回收,即不会造成内存泄漏的情况。

13、同步锁、死锁、乐观锁、悲观锁 (高薪常问) 

同步锁:
当多个线程同时访问同一个数据时,很容易出现问题。为了避免这种情况出现,我们要
保证线程同步互斥,就是指并发执行的多个线程,在同一时间内只允许一个线程访问共享数
据。Java 中可以使用 synchronized 关键字来取得一个对象的同步锁。
死锁:
何为死锁,就是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。
乐观锁:
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是
在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和
CAS 算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类
似于 write_conditio 机制,其实都是提供的乐观锁。在 Java 中 java.util.concurrent.atomic
包下面的原子变量类就是使用了乐观锁的一种实现方式 CAS 实现的。
悲观锁:
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时
候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使
用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了
很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java 中
synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现

14、说一下 synchronized 底层实现原理?(高薪常问) 

1、syn 锁住的是对象,对象里边的组成如下:
Java 的对象布局
必须是要求对象的大小必须是 8 的整数倍
  • 首先是有一个 object header
  • 填充数据 :当对象大小不足 8 的倍数的时候,他会把当前对象填充成 8 的 倍数,假如他现在本身就是 8 的 byte 的倍数,此时填充数据就不用了
  • 成员变量 :就是咱们成员变量2)锁升级
(1) 偏向锁
线程要尝试去加锁,他会去判断当前这个 mark-word 里边是否包含线程 id,如果没有线程
id 的话,他会去利用 cas 把自己的线程 id 写入到 mark-word 里边去第二次这个线程再次
过来的时候,他会去判断当前这个 mark-word 里边是否包含线程 id,如果有了的话,他就
会把他自己的线程 id 和对象头里边的线程 id 进行对比,如果发现是一样的此时就标识获得
到了锁
如果你在没加锁的情况打印对象头:他默认就是 无锁可偏向,如果你没加锁的情况计算了
hashCode 码,无锁不可偏向,
如果此时你加锁无法成为偏向锁,直接膨胀成一把轻量级锁
(2)轻量级锁
  • 升级成轻量级锁三个条件
                你现在已经是无锁不可偏向,此时加锁那么他就直接是一把轻量级锁
                没有关闭延迟偏向锁打开,他会自动成为轻量级锁
                如果程序出现交替执行,他也会成为一把轻量级锁
  • 原理
首先方法压栈,此时这个方法栈帧就压栈,栈帧种就创建两个和锁有关系的空间
displace hrd ,owner
他会将锁里边的 mark-word 里边信息拷贝到 hrd 种
他会用栈帧 owner 指针去指向我们的对象头
对象头中轻量级指针会指向当前创建出来的这个栈帧 锁会把当前的状态修改成 00
如果说完成了以上 4 件事情,那么此时才表示加锁成功,这把锁就是属于当前线程
(3) 重量级锁      原理
  • Java 如果发现要创建一把重量级锁,我们 Java 就会为我们创建一个 C++的 ObjectMonitor,会让对象头中 monitor 指向我们这个 ObjectMonitor 对象如果你进入到 锁内部时,这个 ObjectMonitor 他会 发起汇编指定 monitorenter,当你出 syn 代码代码 块的时候,他会发出 monitorexit 指令如果你在执行 syn 过程中出现了异常,其实上他还 是会执行 monitorexit 这样一个指令
  • 对象头里边 monitor 指针会指向 ObjectMonitor 对象,当多个线程来加锁的 时候他,他们就会执行 monitorenter 指令,进入到 ObjectMonitor 进入到 entrylist 中 等待抢锁,他们会利用 cas 来进行抢锁,如果抢锁成功,ObjectMonitor,他会把他内部 的 owner 的指针去指向咱们抢锁成功 线程,然后会让计数器+1,如果此时是抢锁的线程 是持有锁的线程,那么此时 count 就会再+1 ,释放锁的时候,把 count 进行--,直到 count== 0 的时候就把 owner 置为 null,如果你对线程调用 wait 方法,此时这些被 wait 的线程他就会进入到 waitSet 中,只有当你去调用 notifyall 方法的时候他才会从新开始这 样一套流程
  • 如果是同步方法,那么他执行的 指令 acc_synchronized ,但是这哥们是隐式 调用

 15、synchronized 和 volatile 的区别是什么?(高薪常问)

volatile 本质是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从
主存中读取; synchronized 则是锁定当前变量,只有当前线程可以访问该变量,其他线
程被阻塞住。
volatile 仅能使用在变量级别;synchronized 则可以使用在变量、方法、和类级别的。
volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证
变量的修改可见性和原子性。
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。
volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

 16、synchronized 和 Lock 有什么区别? (高薪常问)

首先 synchronized 是 java 内置关键字,在 javjvm 层面,Lock 是个a 类;
synchronized 无法判断是否获取锁的状态,Lock 可以判断是否获取到锁;
synchronized 会自动释放锁(a 线程执行完同步代码会释放锁;b 线程执行过程中发生
异常会释放锁),Lock 需在 finally 中手工释放锁(unlock()方法释放锁),否则容易造成线
程死锁;
用 synchronized 关键字的两个线程 1 和线程 2,如果当前线程 1 获得锁,线程 2 线程
等待。如果线程 1 阻塞,线程 2 则会一直等待下去,而 Lock 锁就不一定会等待下去,如果
尝试获取不到锁,线程可以不用一直等待就结束了;
synchronized 的锁可重入、不可中断、非公平,而 Lock 锁可重入、可判断、可公平
(两者皆可);
Lock 锁适合大量同步的代码的同步问题,synchronized 锁适合代码少量的同步问题。

 二、集合

1、常见的数据结构

 

数组是最常用的数据结构,数组的特点是长度固定,数组的大小固定后就无法扩容了 ,
数组只能存储一种类型的数据 ,添加,删除的操作慢,因为要移动其他的元素。
是一种基于先进后出(FILO)的数据结构,是一种只能在一端进行插入和删除操作
的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在
栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。
队列是一种基于先进先出(FIFO)的数据结构,是一种只能在一端进行插入,在另一
端进行删除操作的特殊线性表,它按照先进先出的原则存储数据,先进入的数据,在读取数
据时先被读取出来。
链表是一种物理存储单元上非连续、非顺序的存储结构,其物理结构不能只表示数据元
素的逻辑顺序,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列的
结节(链表中的每一个元素称为结点)组成,结点可以在运行时动态生成。根据指针的指向,
链表能形成不同的结构,例如单链表,双向链表,循环链表等。
是我们计算机中非常重要的一种数据结构,同时使用树这种数据结构,可以描述现实
生活中的很多事物,例如家谱、单位的组织架构等等。有二叉树、平衡树、红黑树、B 树、
B+树。
散列表,也叫哈希表,是根据关键码和值 (key 和 value) 直接进行访问的数据结构,
通过 key 和 value 来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。
是计算机学科中一类特殊的数据结构的统称,堆通常可以被看作是一棵完全二叉树的
数组对象。
的定义:图是由一组顶点和一组能够将两个顶点相连的边组成的

2、集合和数组的区别 

区别:数组长度固定 集合长度可变 数组中存储的是同一种数据类型的元素,可以存储基本数据类型,也可以存储引用数据
类型;
集合存储的都是对象,而且对象的数据类型可以不一致。在开发当中一般当对象较多的
时候,使用集合来存储对象。

 3、List 和 Map、Set 的区别

List 和 Set 是存储单列数据的集合,Map 是存储键值对这样的双列数据的集合;
List 中存储的数据是有顺序的,并且值允许重复;
Map 中存储的数据是无序的,它的键是不允许重复的,但是值是允许重复的;
Set 中存储的数据是无顺序的,并且不允许重复,但元素在集合中的位置是由元素的
hashcode 决定,即位置是固定的(Set 集合是根据 hashcode 来进行数据存储的,所以位
置是固定的,但是这个位置不是用户可以控制的,所以对于用户来说 set 中的元素还是无序
的)。

4、 List 和 Map、Set 的实现类 

7671497ab68a402192b2eb758f4e71e9.png

4.1、Connection 接口

List 有序,可重复
ArrayList
优点: 底层数据结构是数组,查询快,增删慢。
缺点: 线程不安全,效率高
Vector
优点: 底层数据结构是数组,查询快,增删慢。缺点: 线程安全,效率低, 已给舍弃了
LinkedList
优点: 底层数据结构是链表,查询慢,增删快。
缺点: 线程不安全,效率高
 
Set 无序,唯一
HashSet
底层数据结构是哈希表。(无序,唯一)
如何来保证元素唯一性?
依赖两个方法:hashCode()和 equals()
LinkedHashSet
底层数据结构是链表和哈希表。(FIFO 插入有序,唯一)
a.由链表保证元素有序
b.由哈希表保证元素唯一
TreeSet
底层数据结构是红黑树。(唯一,有序)
a. 如何保证元素排序的呢?
自然排序
比较器排序
b.如何保证元素唯一性的呢?
根据比较的返回值是否是 0 来决定

4.2、Map 接口有四个实现类 

HashMap
基于 hash 表的 Map 接口实现,非线程安全,高效,支持 null 值和 null 键, 线程
不安全。
HashTable
线程安全,低效,不支持 null 值和 null 键;
LinkedHashMap
线程不安全,是 HashMap 的一个子类,保存了记录的插入顺序;
TreeMap
能够把它保存的记录根据键排序,默认是键值的升序排序,线程不安全。

5、Hashmap 的底层原理 

 

HashMap 在 JDK1.8 之前的实现方式 数组+链表,
但是在 JDK1.8 后对 HashMap 进行了底层优化,改为了由 数组+链表或者数值+红黑树
实现,主要的目的是提高查找效率

409f4fe2e7fc4fe9a2997ef489990441.png

8ef63c3b7a0a42ebae1f5cc39c9bd5e4.png

(1)Jdk8 数组+链表或者数组+红黑树实现,当链表中的元素超过了 8 个以后, 会将链
表转换为红黑树,当红黑树节点 小于 等于 6 时又会退化为链表。
(2)当 new HashMap():底层没有创建数组,首次调用 put()方法示时,底层创建长度为
16 的数组,jdk8 底层的数组是:Node[],而非 Entry[],用数组容量大小乘以加载因子得到
一个值,一旦数组中存储的元素个数超过该值就会调用 rehash 方法将数组容量增加到原来
的两倍,专业术语叫做扩容,在做扩容的时候会生成一个新的数组,原来的所有数据需要重
新计算哈希码值重新分配到新的数组,所以扩容的操作非常消耗性能.
默认的负载因子大小为 0.75,数组大小为 16。也就是说,默认情况下,那么当 HashMap
中元素个数超过 16*0.75=12 的时候,就把数组的大小扩展为 2*16=32,即扩大一倍。
(3)在我们 Java 中任何对象都有 hashcode,hash 算法就是通过 hashcode 与自己进行
向右位移 16 的异或运算。这样做是为了计算出来的 hash 值足够随机,足够分散,还有产
生的数组下标足够随机,
map.put(k,v)实现原理
1)首先将 k,v 封装到 Node 对象当中(节点)。
2)先调用 k 的 hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
3)下标位置上如果没有任何元素,就把 Node 添加到这个位置上。如果说下标对应的
位置上有链表。此时,就会拿着 k 和链表上每个节点的 k 进行 equal。如果所有的 equals
方法返回都是 false,那么这个新的节点将被添加到链表的末尾。如其中有一个 equals
返回了 true,那么这个节点的 value 将会被覆盖。
map.get(k)实现原理
1)、先调用 k 的 hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
2)、在通过数组下标快速定位到某个位置上。重点理解如果这个位置上什么都没有,则返回 null。如果这个位置上有单向链表,那么它就会拿着参数 K 和单向链表上的每一
个节点的 K 进行 equals,如果所有 equals 方法都返回 false,则 get 方法返回 null。
如果其中一个节点的 K 和参数 K 进行 equals 返回 true,那么此时该节点的 value 就
是我们要找的 value 了,get 方法最终返回这个要找的 value。
(4)Hash 冲突
不同的对象算出来的数组下标是相同的这样就会产生 hash 冲突,当单线链表达到一定长度
后效率会非常低。
(5)在链表长度大于 8 的时候,将链表就会变成红黑树,提高查询的效率。

 

6、Hashmap 和 hashtable ConcurrentHashMap 区别 

区别对比一(HashMap 和 HashTable 区别):
(1)HashMap 是非线程安全的,HashTable 是线程安全的。
(2)HashMap 的键和值都允许有 null 值存在,而 HashTable 则不行。
(3)因为线程安全的问题,HashMap 效率比 HashTable 的要高。
(4)Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更适合于单线程
环境,而 Hashtable 适合于多线程环境。一般现在不建议用 HashTable, ①是 HashTable
是遗留类,内部实现很多没优化和冗余。②即使在多线程环境下,现在也有同步的
ConcurrentHashMap 替代,没有必要因为是多线程而用 HashTable。
区别对比二(HashTable 和 ConcurrentHashMap 区别):
HashTable 使用的是 Synchronized 关键字修饰,ConcurrentHashMap 是 JDK1.7
使用了锁分段技术来保证线程安全的。JDK1.8ConcurrentHashMap 取消了 Segment 分
段锁,采用 CAS 和 synchronized 来保证并发安全。数据结构跟 HashMap1.8 的结构类似,
数组+链表/红黑二叉树。
synchronized 只锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不
会产生并发,效率又提升 N 倍。

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/522113.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣刷题--不同的二叉搜索树96

不同的二叉搜索树 该题虽然是一个二叉树的题目 但是使用动态规划做 dp[i]数组的含义:i个节点有多少种组合方式递推公式:dp[i] dp[j] dp[i-1-j] j(0–>i-1)初始化:dp[0]1 dp[1] 1确定递推顺序 i(2–>n) j(0–>i-1)推导一遍 c…

后端说处理了跨域但没有生效

场景: 常见的跨域报错,一般都是由后端进行setHeader/*什么的。但是现在这种情况就是后端说他们做了处理。但是我这边请求还是报错。 withCredentials: with-credentials用来设置是否发送cookie,如果为true就会在跨域请求时候携带cookie&…

DC/DC1A30V高效同步降压转换器H4010

DC/DC 1A30V高效同步降压转换器是一种高频、同步、整流、降压、开关模式转换器,内置功率MOSFET。它可以在宽输入电源范围内实现1.5A峰值输出电流,并具有出色的负载和线路调节性能。此外,该转换器需要最少数量的现成外部元件,并采用…

电脑桌面上表格不见了怎么找回?这5个方法不要错过

在日常的办公和学习中,电脑桌面上的各种文件、文件夹和表格等无疑是我们较为频繁使用的资源。然而,有时我们可能会因为一些操作失误或者电脑问题,突然发现桌面上的某个表格文件神秘失踪了。面对这种情况,很多人可能会感到焦虑和不…

Win11怎么关闭防火墙,win11怎么关闭防火墙对应用的限制

Win11系统如何关闭防火墙呢?有时候我们安装一些软件的时候,屏幕右下角会弹出警告,提示软件被拦截,无法安装成功。如果想要正常安装的话,需要先将防火墙功能给关闭了。由于win11的操作逻辑与win10大不同,所以许多小伙伴不清楚win11如何管理防火墙。接下来,小编跟大家分享…

C语言 | Leetcode C语言题解之第12题整数转罗马数字

题目: 题解: const char* thousands[] {"", "M", "MM", "MMM"}; const char* hundreds[] {"", "C", "CC", "CCC", "CD", "D", "DC"…

beego 官网文档本地环境搭建

beego 官网文档本地环境搭建,为什么要本地环境搭建呢?因为beego 原来的官网文档(https://beego.gocn.vip/)已经不能用了,beego 官网已经在github上说明了,因此如果想方便的看官网文档,就需要在本…

《乡土中国》中国基层传统社会里的一种体系,支配着社会生活的各方面 - 三余书屋 3ysw.net

乡土中国 大家好,今天我们要解读的是费孝通先生的经典著作《乡土中国》。这本书的中文版大约有10万字,我将用30分钟左右的时间为你解读书中的精髓。为什么说中国的根基在于乡土社会?我们应该从哪些方面来理解乡土社会的特征及其重要性&#…

PMP考试难度大吗?和软考比怎么样?

软考和PMP哪个更好考?巧了,两个证都有,我感觉是PMP更好考也更有含金量,软考可以在考过PMP后去考试,基本不用学。PMP是偏向项目管理方向的考试,而软考除了项目管理还要有足够的计算机知识,对没基…

文心一言 VS 讯飞星火 VS chatgpt (231)-- 算法导论17.1 2题

二、证明:如果 k 位计数器的例子中允许 DECREMENT 操作,那么 n 个操作的运行时间可能达到 Θ(nk)。 文心一言: 为了证明如果 k 位计数器的例子中允许 DECREMENT 操作,那么 n 个操作的运行时间可能达到 Θ(nk),我们可…

力扣回溯篇

文章目录 46.全排列78.子集17.电话号码的字母组合39.组数总和79.单词搜索131.分割回文子串 46.全排列 给定一个不含重复数字的数组 nums ,返回其所有可能的全排列 。你可以按任意顺序返回答案。 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],…

C++利用键值对计算某一个数对应的最值及其索引位置

目录 一、算法概述二、代码实现1、计算最值2、计算最值及其索引 三、结果展示 本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法概述 类似下图所示,计算第一列中1或2对应的最…

剑指Offer题目笔记26(动态规划的基础知识)

面试题88: 问题: ​ 一个数组cost的所有数字都是正数,它的第i个数字表示在一个楼梯的第i级台阶往上爬的成本,在支付了成本cost[i]之后可以从第i级台阶往上爬1级或2级。请计算爬上该楼梯的最少成本。 解决方案一:&…

C++学习笔记(16)——vector的使用与模拟实现

文章目录 比喻与理解一、定义二 、在使用层面三、在实现层面四、vector的成员变量五、vector的迭代器六、vector的容器函数七、vector的其他函数1. reserve更新容器空间大小:vector_name.reserve(size_type);2. resize大小:vector_name.resize(size_type…

AcWing---公约数---最大公约数

4199. 公约数 - AcWing题库 思路: 最大整数x一定是最大公约数的因数,所以先用__gcd(a,b)求出a和b的最大公因数,再用O(log(n))的算法求出最大公因数的因数,放到vector中,并将vector排序。利用STL中的upper_bound(res.…

模组网络通用丨蜂窝网络基础知识介绍

在物联网的时代,蜂窝网络成为了连接各种智能设备的重要基础。而在蜂窝网络中,蜂窝模组则是实现物联网连接的关键组件。作为物联网开发人员,了解蜂窝网络的基础知识是非常重要的。本文详细解答了6个在开发过程的常见问题,帮助客户更…

自然语言处理NLP概述

大家好,自然语言处理(NLP)是计算机科学领域与人工智能领域中的一个重要方向,其研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。本文将从自然语言处理的本质、原理和应用三个方面,对其进行概述。 一、NLP的本质 NLP是一种…

linux常用目录结构(目录命令)--6986字详谈

前面与大家讨论了linux的发展与由来(这一块挺多的,小编还没有编写完成,希望大家理解),紧接着谈到了vmware安装及运行所存在的故障(鉴定错误,虚拟机没有网,蓝屏等常见现象的总结及处理…

Mysql5.7 yum 简单/快速安装

Centos7下MySql安装及配置过程,简单直装版 目录 操作步骤 一、检查linux是否已安装MySql二、清除MySQL(适用重新安装) 1、删除MySQL及其依赖包2、查询遗留的目录3、删除遗留的目录三、开始安装MySQL 1、下载并添加库2、安装MySQL包3、设置My…

Qt环形颜色选择控件, 圆环颜色选择器

参考文章Qt编写自定义控件:环形颜色选择控件_qconicalgradient圆环渐变-CSDN博客 感谢作责提供的方法,下面程序的基础思路同参考文章。 为了更方便使用,这个选择器是基于64色表的,会显示选中的索引和色值。颜色选择时计算方式也…