云计算面试题

打印 上一主题 下一主题

主题 664|帖子 664|积分 1992

5.20日

java的集合体系结构

它提供了一组接口、类和算法,用于存储和管理对象集合。Java的集合框架包罗多个根本接口,如Collection、List、Set、Map等。Collection是集合层次结构的根接口,代表一组对象;List是有序集合,可以包含重复元素;Set是不包含重复元素的集合;Map是键值对的集合。这些接口提供了各种操作,如搜索、排序、插入、操作和删除,使数据操作变得简朴快捷。
hashmap的实现原理

HashMap是Java中的一个紧张数据结构,它基于哈希表实现。HashMap通过将键映射到值来存储数据,具有快速的查找和插入性能。在HashMap中,键是唯一的,而值可以重复。HashMap的实现原理是通过计算键的哈希码,然后将其映射到内部数组的索引位置,以实现快速的查找和插入操作。在处理哈希冲突时,HashMap使用链表或红黑树来解决。
抽象类和接口的区别?


  • 抽象类使用abstract定义 接口使用interface定义
  • 接口里面的方法默认使用是用public abstract修饰的,接口里面的属性都是静态常量,默认使用public static final修饰的
  • 抽象类包含抽象方法和非抽象方法,非抽象方法需要有方法体
  • java8之前接口中的方法都是抽象方法 ,java8之后 接口可以写默认方法,默认方法可以写方法体写代码逻辑了
抽象类是一种类,可以包含抽象方法和详细方法,不能被实例化,需要子类继续并实现其抽象方法。接口是一种纯抽象的范例,只包含常量和抽象方法的定义,不能包含详细方法的实现。一个类可以实现多个接口,但只能继续一个抽象类。因此,抽象类提供了一种代码重用和继续的机制,而接口则提供了一种更机动的实现多态和组合的方式。
为什么java不支持多继续

Java不支持多继续是为了避免多继续可能引发的复杂性和歧义。多继续会导致菱形继续等题目,增长代码的复杂性和难以维护性。Java通过接口的方式实现了类与类之间的多重继续,使得代码结构更清楚、机动,并且避免了多继续可能带来的题目。
java的异常体系

Java异常分为可检查异常(Checked Exception)和不可检查异常(Unchecked Exception)。可检查异常需要在代码中显式处理,如IOException;不可检查异常通常是运行时异常,如NullPointerException。异常处理通过try-catch-finally块来捕获和处理异常,包管步伐的稳固性和可靠性。
5.21日

为什么list在foreach中不能删除数据,怎样想删除数据怎么办

因为foreach循环实际上是通过迭代器来遍历集合的,而在foreach循环中无法直接访问迭代器的remove方法。假如在foreach循环中尝试直接删除元素,会导致集合结构发生变化,从而抛出ConcurrentModificationException(并发修改)异常。为了安全地从集合中删除元素,应该使用Iterator迭代器来举行操作。通过使用Iterator,可以在遍历集合的同时安全地删除元素,而不会引发异常。
什么是微服务架构? 什么是集群

微服务架构是一种软件架构设计风格,其中软件体系被拆分为一组小型、独立的服务单元,每个服务单元都运行在自己的进程中,并通过轻量级通信机制(通常是HTTP API)举行交互。每个微服务都专注于实行特定的业务功能,可以独立摆设、扩展和维护。微服务架构的优势包罗提高体系的机动性、可伸缩性和可维护性,同时降低了体系的耦合度和复杂性。
集群是指将多台计算机(通常是服务器)连接在一起,以共同完成某项使命或提供某种服务。在集群中,这些计算机通过网络通信协作,共享负载和资源,以提高体系的性能、可靠性和可用性。
5.23日

HashMap是怎样解决hash冲突的

采用链式寻址法解决,之所以会产生hash冲突,因为hashmap底层是数据组+加链表构成的,当往hashmap中存放数据的时间,因为是key,value形式的,他会根据key的hashcode方法获取hashcode值,因为要落到数组结构中,那么就使用了位与运算,举行计算落到详细的数组中,假如两个key他们经过计算获取到的数组位置是一样的,那么就生产的hash冲突的题目。
**链地点法(开放寻址法的一种):**HashMap在每个哈希桶(bucket)中存储一个链表(在 Java 8 及以后版本中,当链表长度凌驾一定阈值时会转换为红黑树以优化性能)。当两个差别的键具有相同的哈希值时,它们会被存储在同一个哈希桶的链表中。因此,查找一个键时,首先根据哈希值找到对应的哈希桶,然后遍历该桶中的链表来找到详细的键。
**重新哈希:**固然HashMap自己不直接实现重新哈希来解决冲突,但在某些环境下,我们可以通过实现高质量的hashCode()方法来淘汰冲突。一个好的hashCode()方法应该尽量分散地生成哈希值,以淘汰哈希冲突的可能性。
**扩容:**当哈希表中的元素数量凌驾某个阈值(默认为容量的 0.75)时,HashMap会主动扩容(即创建一个新的、更大的哈希表,并将原哈希表中的全部元素重新哈希并放入新表)。扩容可以淘汰哈希冲突的可能性,因为新的哈希表有更多的桶来存储元素
**使用红黑树(Java 8 及以后版本):**当链表长度凌驾某个阈值(默认为 8)时,Java 8 中的HashMap会将链表转换为红黑树。红黑树是一种自平衡的二叉搜索树,它可以在 O(log n) 的时间复杂度内完成查找、插入和删除操作,从而提高了HashMap在哈希冲突较多时的性能
HashMap 的 put 流程

HashMap的put流程是 Java 集合框架中非常紧张的一个操作,它用于在HashMap中插入或更新键值对。以下是HashMap的put方法的大致流程(基于 Java 8 及之后的版本):
1.计算哈希值 2.确定桶的位置 3.处理哈希冲突 4.扩容 5.返回旧值
计算哈希值:
当调用put(K key, V value)方法时,首先会调用key对象的hashCode()方法来计算哈希值。
确定桶的位置:
将计算得到的哈希值通过某种算法(通常是哈希值对数组长度取模)转换为数组索引,确定键值对应该存储在哪个桶(bucket)中。
处理哈希冲突:


  • 假如桶中已经有元素(链表或红黑树),说明发生了哈希冲突。此时会举行以下操作:
  • 假如桶中是一个链表,遍历链表,使用equals()方法查找是否存在相同的键。
  • 假如找到了相同的键,则使用新的值更换旧的值(更新操作)。
  • 假如没有找到相同的键,则将新的键值对添加到链表的末尾。
  • 假如链表长度凌驾了某个阈值(TREEIFY_THRESHOLD,默认为 8),并且数组大小大于或即是MIN_TREEIFY_CAPACITY(默认为 64),则将链表转换为红黑树。
扩容:
假如HashMap中的元素数量凌驾了数组长度和加载因子(load factor)的乘积(默认加载因子为 0.75),则触发扩容操作。创建一个新的数组,其长度是原数组长度的两倍。将原数组中的全部元素重新哈希并放入新数组中。
返回旧值(可选):
假如键值对是新的(即没有发生键冲突),则返回null;假如更换了旧值,则返回被更换的旧值。
5.24日

HashMap的扩容机制

扩容必须满意两个条件:
HashMap的扩容机制是HashMap在动态调整其内部数组大小以应对元素数量增长的紧张机制
1、 存放新值的时间当前已有元素的个数必须大于即是阈值
2、 存放新值的时间当前存放数据发生hash碰撞(当前key计算的hash值换算出来的数组下标位置已经存在值)

  • 扩容触发条件:HashMap的扩容紧张基于两个条件。首先,当HashMap中的元素数量(size)凌驾了阈值(threshold)时,会触发扩容。这个阈值是HashMap的容量(capacity)与加载因子(load factor)的乘积。在Java的HashMap实现中,默认的加载因子是0.75,这意味着当HashMap中的元素数量达到了其容量的75%时,就会触发扩容。(默认长度16)
  • 扩容过程:当HashMap需要扩容时,会创建一个新的数组,其容量是原数组的两倍。然后,HashMap会重新计算每个元素的哈希值,并根据新的容量确定每个元素在新数组中的位置。这个过程被称为“rehashing”。
HashMap 是线程安全的吗?多线程下会有什么题目?

HashMap 在 Java 中是非线程安全的。在多线程环境下使用 HashMap 可能会导致以下题目:

  • 数据差别等性:由于 HashMap 的 put、get、remove 等操作没有内置的同步机制,多个线程可以同时修改 HashMap 的结构或内容,这可能导致数据的差别等性,如数据丢失、重复插入或覆盖。
  • 死循环题目:在 Java 7 中,尤其当存在哈希碰撞并且多个线程同时插入时,可能会导致链表形成环状结构,进而引发死循环。固然这个题目在 Java 8 中由于引入了红黑树作为散列冲突严重时的解决方案而得到缓解,死循环的题目根本被避免,但 HashMap 自己仍然是非线程安全的。
  • 扩容时的题目:当 HashMap 需要扩容时,假如没有得当的同步控制,多个线程同时举行扩容操作可能会导致数据错乱,比如元素被错误地放置到新的桶中,或某些元素没有被精确地迁徙。
  • 可见性题目:线程修改 HashMap 的操作可能对其他线程不可见,这是由于 Java 内存模型中关于数据同步的规定,一个线程修改的数据可能不会立刻对其他线程可见。
解决办法
可以通过外部同步锁解决多线程同步
也可以通过concurrentHashMap举行代替
5.25日

你知道concurrentHashmap吗,他的原理是什么

Java 中的一个并发哈希表实现,用于在多线程环境下安全地存储和操作键值对
它的原理紧张基于两个方面:分段锁和使用 CAS (Compare and Swap) 操作。

  • 分段锁:ConcurrentHashMap 将整个数据结构分割成多个段(Segment),每个段相当于一个小的哈希表,每个段都有自己的锁。如允许以减小锁的粒度,差别的段可以被差别的线程同时访问,提高并发性能。当一个线程对某个段举行操作时,只有这个段会被锁定,其他段的操作不会被壅闭。
  • CAS 操作:在 ConcurrentHashMap 的实现中,对于差别的操作,比如插入、删除、更新等,都是通过 CAS 操作来实现的。CAS 是一种乐观锁技术,它答应多个线程同时尝试更新同一个变量的值,但只有一个线程能够成功,其他线程需要重试。这种方式在并发环境下能够提供较高的性能。
为什么在JDK8中HashMap要转成红黑树

在JDK8中,HashMap在某些环境下会将链表转换为红黑树,这是为了解决在链表过长时导致的性能题目。
原因是什么

提高性能
当链表长度凌驾一定阈值(默认为8)时,HashMap会将链表转换为红黑树,如允许以将查找、插入等操作的时间复杂度从O(n)降低到O(log n),提高了HashMap在大数据量环境下的性能。
在链表长度大于8的时间,将后面的数据存在红黑树中,以加快检索速度
解决了什么题目

红黑树的引入解决了HashMap在处理大量数据时的性能题目,使得HashMap在更广泛的场景下都能保持较好的性能表现。
为什么不使用二叉树

假如使用二叉树有序化的数据 就有可能导致变成另一个列表
5.27日

为什么会有跨域,解决跨域的原理是什么

1.什么是跨域
跨域:指的是浏览器不能实行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限定。
• 同源策略:是指协议,域名,端口都要相同,其中有一个差别都会产生跨域
2.为什么会有跨域
为了网络安全 防止不安全的请求 ,浏览器设置了一个同源策略,域名,端口,协议全部相同,就叫做同源。当页面在实行一个脚本时,会检查访问的资源是否同源,假如不是,就会报错。在实际开发中,常常会有跨域加载资源的需求,避免不了跨域请求,所以就出现了跨域
3.跨域的解决方案
1、 后端加注解
2、nginx反向署理


  • 利用nginx把跨域反向署理为不跨域,支持各种请求方式
3、设置浏览器属性


  • 方法:在浏览器中设置参数--args --disable-web-security(留意有空格)。
4、前端代码
5、CORS(跨域资源共享)


  • 一种由 W3C 提出的跨域解决方案。它答应服务器在响应头中设置一些特殊的字段(如 Access-Control-Allow-Origin),来告诉浏览器哪些源可以访问该资源。浏览器在吸收到响应后,会检查这些字段的值,并根据这些值来决定是否答应跨域请求。
6、JSONP (JSON with Padding)


  • 原理:利用<script>标签不受同源策略限定的特性,通过<script>标签的src属性发送带有callback参数的GET请求,服务端返回数据时,将JSON数据作为参数传入该函数中,以此实现跨域加载数据。
5.28日

@RestController和@Controller的区别

@Controller标识当前类是SpringMVC Controller处理器,而@RestController则只负责数据返回
@Controller


  • 用途:
    @Controller 注解紧张用于定义一个控制器类,该类负责处理用户的HTTP请求,并返回相应的视图。
  • 返回范例:
    在 @Controller 中,处理方法通常返回一个字符串,该字符串代表要渲染的视图的名称。框架会根据这个视图名称查找并渲染相应的视图。
  • 视图解析:
    @Controller 类的处理方法返回的字符串通常被解释为视图名称,然后由视图解析器解析为实际的视图。
@RestController


  • 用途:
    @RestController 注解是 @Controller 的一个特化版本,专门用于构建 RESTful {/ ˈrestfl / }风格的Web服务。它组合了 @Controller 和 @ResponseBody 注解的功能。
  • 返回范例:
    在 @RestController 中,处理方法的返回值会直接作为HTTP响应的主体内容,而不会被解释为视图名称。通常,@RestController 返回的是JSON或XML格式的数据。
  • 视图解析:
    由于 @RestController 不涉及视图解析,因此它不关心视图名称或视图解析器。
你们项目是怎样设置全局异常处理的

在项目中设置全局异常处理是一种良好的实践,可以帮助开发人员更好地管理和处理应用步伐中的异常环境。在Java中,特别是在Spring框架中,可以通过@ControllerAdvice注解来实现全局异常处理。全局异常处理的设置可以在整个应用步伐中捕获未处理的异常,并提供同一的方式来处理这些异常,从而提高应用步伐的结实性和可维护性。

  • 创建自定义异常
  • 创建全局异常处理器
  • 创建测试控制器
为什么要设置全局异常处理呢?全局异常处理的好处包罗:
同一异常处理:通过设置全局异常处理,可以确保应用步伐在遇到异常时有同等的处理方式,避免在各个地方重复编写异常处理逻辑,提高代码的复用性和可维护性。
提高用户体验:全局异常处理可以帮助应用步伐更友爱地向用户展示错误信息,提高用户体验。比方,可以同一返回特定格式的错误信息或页面,让用户更容易理解和处理异常环境。
便于日志记录和监控:通过全局异常处理,可以集中记录应用步伐中的异常环境,便于日志记录和监控。这有助于开发人员及时发现和解决潜在的题目。
提高应用步伐的稳固性:通过同一处理异常,可以避免未捕获的异常导致应用步伐崩溃或出现不可预料的行为,从而提高应用步伐的稳固性。
在Spring框架中,可以通过创建一个带有@ControllerAdvice注解的类来实现全局异常处理。在这个类中,可以定义异常处理方法,针对差别范例的异常举行处理,以及返回得当的响应给客户端。如允许以确保应用步伐在发生异常时有同一的处理逻辑。
@Resource和@Autowired

spring中,@Resource和@Autowired都是做bean的注入时使用。使用过程中,有时间@Resource 和 @Autowired可以更换使用;有时,则不可以。
共同点


  • @Resource和@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰结果相同,可以相互更换,不影响使用。
差别点


  • @Resource是Java自己的注解,@Resource有两个属性是比较紧张的,分是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的范例。所以假如使用name属性,则使用byName的主动注入策略,而使用type属性时则使用byType主动注入策略。假如既不指定name也不指定type属性,这时将通过反射机制使用byName主动注入策略。
  • @Autowired是spring的注解,是spring2.5版本引入的,Autowired只根据type举行注入,不会去匹配name。假如涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。
什么是spring的ioc

Spring的IoC(控制反转)是Spring框架的一个关键概念,它指的是将对象的创建和依赖关系的管理交给Spring容器来完成,而不是在代码中直接创建和管理对象。IoC的焦点思想是将对象之间的依赖关系从步伐中剥离出来,通过外部设置来管理,从而实现了松耦合(Loose Coupling)。
在Spring中,IoC容器负责实例化、设置和组装对象,使得对象之间的依赖关系可以通过设置文件举行定义和管理。通过IoC容器,我们只需要在设置文件中声明对象之间的依赖关系,而不需要在代码中直接实例化对象大概通过构造函数传递依赖,从而使得体系更加机动、可扩展和易于维护。
Spring提供了两种紧张的IoC容器:BeanFactory和ApplicationContext。BeanFactory是Spring框架最基础的IoC容器,提供了根本的IoC功能,而ApplicationContext是BeanFactory的扩展,提供了更多的企业级特性,如国际化支持、事件发 布、资源加载等功能。
总的来说,Spring的IoC容器实现了控制反转,将对象的创建和依赖关系的管理交给了容器,从而降低了组件之间的耦合度,提高了代码的机动性和可维护性。
5.30日

ArrayList 和 LinkedList 有什么区别,分别适用于那种开发场景

ArrayList 和 LinkedList 在Java中是两种差别的数据结构实现,它们适用于差别的开发场景。
ArrayList 是基于动态调整大小的数组实现的 适用于频仍随机访问元素,它支持通过索引快速访问元素 ,内存占用方面比较紧凑 适合大量元素的存储
而 LinkedList 是基于双向链表实现的,适用于需要频仍删除、插入元素的场景,但是likedList不支持随机访问 是按照顺序遍历链表来访问元素的。
根据详细的需求和操作范例,选择合适的数据结构可以提高步伐的效率和性能。一般来说,假如需要频仍随机访问元素,使用 ArrayList 更合适;假如需要频仍插入、删除元素,使用 LinkedList 更合适。
ArrayList 的扩容机制

ArrayList 的扩容机制是在元素数量凌驾当前容量时,会创建一个新的更大容量的数组,并将原数组中的元素复制到新数组中。
ArrayList 的底层是用动态数组来实现的。我们初始化一个ArrayList 集合还没有添加元素时,其实它是个空数组,只有当我们添加第一个元素时,内部会调用扩容方法并返回最小容量10,也就是说ArrayList 初始化容量为10。 当前数组长度小于最小容量的长度时(前期容量是10,当添加第11个元素时就就扩容),便开始可以扩容了,ArrayList 扩容的真正计算是在一个grow()里面,新数组大小是旧数组的1.5倍,假如扩容后的新数组大小还是小于最小容量,那新数组的大小就是最小容量的大小,后面会调用一个Arrays.copyof方法,这个方法是真正实现扩容的步骤。
是一个数组结构的存储容器 默认数组长度是10 也可以在构建arrayList的时间 指定初始长度,当我们不断在arrayList里面填加数据的时间当添加的数据凌驾了10 那么arrayList就没有多有的容量去存储后面的数据 那arrayList就会主动扩容
原理是什么
原理是为了包管在添加元素时能够保持较好的性能,避免频仍地举行数组扩容操作。
当 ArrayList 的容量不足以容纳新元素时,会实行以下操作:
创建一个新的数组,通常是当前容量的 1.5 倍大小。
将原数组中的元素复制到新数组中。
更新 ArrayList 内部的引用指向新数组。
添加新元素到新数组中。
这种扩容机制包管了在大部门环境下,添加元素的时间复杂度为 O(1)。但是,在扩容时会涉及元素的复制操作,因此在添加大量元素时可能会产生一定的性能开销。
了解 ArrayList 的扩容机制有助于理解其内部工作原理,以及在实际开发中更好地优化数据结构的使用。
ArrayList 和 LinkedList 有什么区别

ArrayList基于动态调整大小的数组实现的,而 LinkedList基于双向链表实现的。

  • 内部实现:

    • ArrayList 内部使用动态数组来存储元素,因此在读取数据时速度较快。
    • LinkedList 内部使用双向链表来存储元素,不需要举行内存位移操作,因此在数据操作时速度较快

  • 操作性能

    • ArrayList 适合频仍读取数据,对于访问数据较为高效,。
    • LinkedList 适合频仍操作数据,对于数据操作(插入、删除)较为高效

  • 接口实现

    • ArrayList 只实现了 List 接口,因此只能作为列表使用。
    • LinkedList 实现了 List 和 Deque 接口,可以同时作为列表和队列使用。

  • 访问时间

    • ArrayList 提供 O(1) 的时间复杂度用于基于索引的访问,但在插入和删除时为 O(n)。
    • LinkedList 提供 O(1) 的时间复杂度用于插入和删除,但在基于索引的访问时为 O(n)。

  • 内存使用

    • ArrayList 的元素存储在连续的内存位置,内存利用更高效。
    • LinkedList 需要额外的指针1来存储前后节点的地点,因此内存斲丧更大。

  • 拓展

    • 在双向链表(doubly linked list)中,每个节点除了存储数据外,还需要存储指向前一个节点和后一个节点的指针(或引用)。这两个指针分别称为 prev_node 和 next_node。通过这两个指针,可以在链表中轻松地举行向前和向后遍历,实现双向的数据访问和操作。
    • 由于每个节点都需要存储额外的指针来指向前后节点,这就导致了 LinkedList 内存斲丧更大的环境。相比之下,像 ArrayList 如许的动态数组结构只需要存储元素自己,不需要额外的指针来连接节点,因此在内存斲丧上通常会更加高效。

分别适用于那种开发场景

ArrayList 适用于需要频仍随机访问元素的场景,因为它支持通过索引快速访问元素,时间复杂度为 O(1)。别的,ArrayList 在内存占用方面比较紧凑,适合大量元素的存储。
LinkedList 适用于需要频仍插入、删除元素的场景,因为在链表中插入和删除元素的时间复杂度为 O(1)。但是,LinkedList 不支持随机访问,需要按顺序遍历链表来访问元素。
ArrayList 的扩容机制了解吗,

ArrayList 的扩容机制是在元素数量凌驾当前容量时,会创建一个新的更大容量的数组,并将原数组中的元素复制到新数组中。
ArrayList 扩容机制的原理

当 ArrayList 的容量不足以容纳新元素时,会实行以下操作:

  • 创建一个新的数组,通常是当前容量的 1.5 倍大小。
  • 将原数组中的元素复制到新数组中。
  • 更新 ArrayList 内部的引用指向新数组。
  • 添加新元素到新数组中。
  • 默认长度10
这种扩容机制包管了在大部门环境下,添加元素的时间复杂度为 O(1)。但是,在扩容时会涉及元素的复制操作,因此在添加大量元素时可能会产生一定的性能开销。

   

  • 指针实际上是指向内存中另一个位置的变量。在 Java 中,固然没有直接的指针概念,但在实现 LinkedList 这种数据结构时,需要使用类似指针的概念来连接节点 ↩︎

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

干翻全岛蛙蛙

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表