面试(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 倍。

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型日报#0409:Llama 3下周发布、特斯联20亿融资、Karpathy新项目

导读: 欢迎阅读《AI大模型日报》,内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 120亿Stable LM 2上线即开源!2万亿token训练,碾压Llama 2 70B 摘要: Stable LM 2 12B参数版本发布&#x…

vue项目中使用html2canvas 下载当前页面(动态页面宽度、高度)

老规矩先上效果图: 需求1、 只要上图红色区域的内容下载,就需要计算红色区域的内容的动态宽度、高度。 需求2、当前页面可视区域的内容下载,上传按钮下面的所有内容。 一、 安装依赖 :安装html2canvas插件 npm isntall html2canvas 或者…

Docker容器嵌入式开发:在Ubuntu上配置Postman和flatpak

在 Ubuntu 上配置 Postman 可以通过 Snap 命令完成,以下是所有命令的总结: sudo snap install postmansudo snap install flatpak在 Ubuntu 上配置 Postman 和 Flatpak 非常简单。以下是一些简单的步骤: 配置 Flatpak 安装 Flatpak&#x…

OpenHarmony实战开发-如何实现一个小鸟避障游戏。

介绍 本示例用于验证OpenHarmony提供的Stage模型,Canvas组件做小游戏的能效是否符合预期,以及验证资源调度子系统的API接口是否符合后台规范运行的预期。 效果预览 使用说明 1.点击ConnectService按钮,创建一个ServiceAbility并连接。 2.…

数据的属性与相似性

目录 一、数据集的结构(一)二维表(二)数据矩阵 二、属性的类型(一)连续属性(二)离散属性(三)分类属性(四)二元属性(五&…

【图论】图的存储--链式前向星存图法以及深度优先遍历图

图的存储 介绍 无向图-就是一种特殊的有向图-> 只用考虑有向图的存储即可 有向图 邻接矩阵邻接表 邻接表 存储结构: (为每一个点开了一个单链表,存储这个点可以到达哪个点) 1:3->4->null2:1->4->null3:4->null4:null 插入一条新的边 比如要插一条边&am…

Go语言不能常量取址!?

题如下图 在软件开发中,常量是一种重要的编程元素,它们在程序中起到固定值的作用被大量使用 Go语言中的常量取址 在 Go 语言中,常量是无法被取址的。这意味着我们不能使用取址操作符 & 来获取常量的地址。例如: const a …

vue3移动端H5 瀑布流显示列表

以上效果 是之前发送的改进版 waterList <template><view class"pro-cons" v-if"data.length"><view class"cons-left"><template v-for"(item, index) in data"><template v-if"(index 1) % 2 1…

scala代码中报Cannot resolve symbol %

1、问题复现 2、解决 &#xff08;1&#xff09; &#xff08;2&#xff09; &#xff08;3&#xff09;检查返回类型&#xff0c;应该是Int 我之前用的&#xff08;.var&#xff09;自动生成返回值&#xff0c;他生成的类型是[Range.Inclusive]&#xff0c;这个类型是scala …

Spring-IoC 基于xml管理

现大多使用注解方式&#xff0c;xml方式并不简洁&#xff0c;本文仅记录xml用作基础学习。 0、前提 首先在父项目的pom.xml中配置好依赖们。然后子模块也可以使用这些依赖。 在resource目录下创建Spring的xml文件&#xff0c;名称无要求&#xff0c;本文使用bean.xml。文件最…

vmware 一打开虚拟机就蓝屏重启

按照正常步骤安装完镜像后&#xff0c;点击 开启此虚拟机 &#xff0c;直接出现下图所示蓝屏&#xff0c;然后重启。 解决的办法是通过修改 启用或关闭windows功能 里的选项&#xff0c;如下图&#xff0c;勾选上 Windows虚拟机监控程序平台 和 虚拟机平台 两项。然后重启电脑…

海外仓的出入库流程有什么痛点?位像素海外仓系统怎么提高出入库效率?

随着跨境电商的蓬勃发展&#xff0c;海外仓是其中不可或缺的一个关键环节。而货物的出库与入库则是海外仓管理中的一个核心业务流程&#xff0c;它的运作效率直接影响到整个跨境物流的效率和客户体验。今天&#xff0c;让我们具体来看一看关于海外仓出入库的流程&#xff0c;其…

Transformer详解和知识点总结

目录 1. 注意力机制1.1 注意力评分函数1.2 多头注意力&#xff08;Multi-head self-attention&#xff09; 2. Layer norm3. 模型结构4. Attention在Transformer中三种形式的应用 论文&#xff1a;https://arxiv.org/abs/1706.03762 李沐B站视频&#xff1a;https://www.bilibi…

正则问题【蓝桥杯】/dfs

正则问题 dfs 刚开始用的是栈&#xff0c;没有想到dfs… #include<iostream> #include<stack> using namespace std; string s; int pos; int dfs() {//ans表示到当前位置最多的x数目//num表示暂存的x数目int num0,ans0;while(pos<s.size()){if(s[pos](){pos;…

虚拟机VMware的下载、注册码(Mac与Windows)

1. 虚拟机的下载 windows 版的虚拟机叫 VMware Workstation mac版的虚拟机叫 VMware Fusion 官网下载地址: window 下载地址 https://www.vmware.com/content/vmware/vmware-published-sites/us/products/workstation-pro.html mac 下载地址 https://www.vmware.com/prod…

C++ STL

C STL&#xff08;标准模板库&#xff09;是一套功能强大的 C 模板类&#xff0c;提供了通用的模板类和函数&#xff0c;这些模板类和函数可以实现多种流行和常用的算法和数据结构&#xff0c;如向量、链表、队列、栈。 学习重点&#xff1a; 组件描述容器&#xff08;Contai…

Linux:文本编辑器 - vim

Linux&#xff1a;文本编辑器 - vim vim基本操作普通模式模式切换移动光标复制粘贴删除替换撤销 底行模式行号查找 vim基本操作 Vim(Vi Improved)是一款功能强大的文本编辑器&#xff0c;是Unix/Linux系统中广泛使用的编辑器之一。它源于上世纪70年代开发的Vi编辑器&#xff0…

在Linux中安装Android Studio(ubuntu22.04)

在Linux中安装Android Studio 准备工作 系统&#xff1a;ubuntu 22.04 位数&#xff1a;64bit 安装要求&#xff1a; 安装流程 1.下载安装包 打开Android Studio官网 把Android Studio的安装包下载下来 2.安装 为了防止丢失&#xff0c;把解压好的文件夹移到 /usr/local…

斐讯E1拆机焊接TTL救砖

从老家的柜子里翻出来一台斐讯E1&#xff0c;老家在用的是斐讯K2P&#xff0c;300M宽带&#xff0c;房间和大部分位置wifi5足够跑满了&#xff0c;一直懒得升级&#xff0c;也足够用了。 不过发现部分位置信号比较弱&#xff0c;都不到50M&#xff0c;考虑插上E1做个AP中继&…

网络安全---非对称数据加密签名验证

一、课题描述 三位同学一组完成数据的非对称加密和数字签名验证传输。 三位同学分别扮演图中 Alice、Bob 和 CA 三个角色&#xff0c;Bob 和 Alice 从 CA 中获得数字证书、Bob 向 Alice 发送秘密发送一段加密并签名后的信息&#xff0c;Alice 获取 Bob 发送的加密信息&#x…