携程Java后端实习一面

携程的面试比较注重八股文和项目,算法相关没有字节腾讯严厉,大家参加携程的技术岗面试需要重视八股文和项目细节,要学会深挖项目,希望大家早日oc😊👍

HashMap底层原理,扩容机制,从并发问题引出ConcurrentHashMap,问如何上锁

HashMap底层原理

  • HashMap 基于数组和链表(在 JDK 1.8 之后引入了红黑树)实现。它通过哈希函数将键映射到数组的索引位置上。
  • 当发生哈希冲突时,会将相同索引位置的元素存储在一个链表中或转换为红黑树。

扩容机制

  • 当 HashMap 中的元素数量超过数组容量的负载因子(默认 0.75)时,会触发扩容操作,将容量加倍并重新分配所有元素到新的数组中。
  • 扩容时需要重新计算所有元素的哈希值,并重新插入到新的数组位置上。

并发问题与 ConcurrentHashMap

  • HashMap 在多线程环境中会出现数据不一致的问题,例如死循环、数据丢失等。
  • ConcurrentHashMap 通过分段锁机制进行并发控制,将整个 Map 分成多个 Segment,每个 Segment 独立加锁,减少锁竞争。
  • JDK 8 之后,ConcurrentHashMap 改用 CAS(Compare-And-Swap)和 Synchronized 结合的方式来提高并发性能。

线程通信的方式

  1. wait() 和 notify()/notifyAll():通过对象监视器进行通信,wait() 使线程等待,notify() 唤醒等待的线程。
  2. Condition:Java 5 引入的更灵活的线程通信机制,与 ReentrantLock 结合使用。
  3. 阻塞队列(BlockingQueue):生产者-消费者模式下常用,如 ArrayBlockingQueue、LinkedBlockingQueue。
  4. 信号量(Semaphore):控制同时访问特定资源的线程数量。
  5. 管道流(PipedInputStream 和 PipedOutputStream):用于线程间数据传输。

线程池参数以及线程池的好处

线程池参数

  1. corePoolSize:核心线程数,始终保持在线的线程数量。
  2. maximumPoolSize:最大线程数,线程池能容纳的最大线程数。
  3. keepAliveTime:空闲线程存活时间,当线程数超过核心线程数时,多余的空闲线程会在指定时间后终止。
  4. unit:keepAliveTime 的时间单位。
  5. workQueue:用于存放等待执行任务的队列。
  6. threadFactory:线程工厂,用于创建新线程。
  7. handler:拒绝策略,当任务队列已满且无法继续创建线程时,处理新任务的策略。

线程池的好处

  1. 重用线程:减少了频繁创建和销毁线程的开销。
  2. 控制最大并发数:通过配置最大线程数来控制并发数量,防止系统资源耗尽。
  3. 管理任务队列:有助于任务的排队和调度。
  4. 提高响应速度:线程池中的线程可以及时处理新任务,减少等待时间。

Mysql索引底层数据结构,用B+树的好处

Mysql索引底层数据结构

  • B+树 是 MySQL 索引的主要数据结构,适用于大多数存储引擎,如 InnoDB。
  • B+树是一种平衡树,所有叶子节点在同一层,并通过双向链表连接。

B+树的好处

  1. 有序性:有助于范围查询和排序操作。
  2. 磁盘读写效率高:B+树节点包含多个元素,一次磁盘读取可以获取更多数据,减少磁盘I/O次数。
  3. 查询效率高:通过树的平衡性保证查询的时间复杂度为 O(log n)。
  4. 适合范围查询:通过叶子节点的链表,可以高效地进行范围查询。

索引的类型

  1. 主键索引(Primary Key Index):唯一标识表中的每一行,不允许重复和空值。
  2. 唯一索引(Unique Index):保证列中的值唯一,但允许空值。
  3. 普通索引(Index):加速查询,没有唯一性限制。
  4. 全文索引(Full-text Index):用于全文搜索,如匹配关键字。
  5. 组合索引(Composite Index):在多个列上创建的索引,加速多条件查询。

如何优化查询语句

  1. 使用合适的索引:建立并使用索引,避免全表扫描。
  2. 选择合适的字段:只查询必要的字段,减少数据传输量。
  3. 避免使用 SELECT *:明确指定查询的列。
  4. 使用 WHERE 子句过滤数据:减少结果集的大小。
  5. 避免在 WHERE 子句中进行函数运算:可能导致索引失效。
  6. 使用 JOIN 代替子查询:提高查询效率。
  7. 适当使用 LIMIT:限制结果集大小,减少不必要的数据处理。
  8. 分析查询执行计划:使用 EXPLAIN 关键字查看查询的执行计划,找出瓶颈。

网络七层模型和四层模型的区别

网络七层模型(OSI模型)

  1. 物理层:传输原始比特流。
  2. 数据链路层:提供节点间的数据传输,进行帧的传输和纠错。
  3. 网络层:负责数据包的路由和转发。
  4. 传输层:提供端到端的通信,确保数据完整性和可靠传输。
  5. 会话层:管理会话,控制建立、维护和终止会话。
  6. 表示层:数据的表示、加密和解密、数据格式转换。
  7. 应用层:提供应用服务,如HTTP、FTP、SMTP等。

四层模型(TCP/IP模型)

  1. 网络接口层:对应OSI模型的物理层和数据链路层。
  2. 互联网层:对应OSI模型的网络层。
  3. 传输层:对应OSI模型的传输层。
  4. 应用层:对应OSI模型的会话层、表示层和应用层。

输入网址到网页显示,期间发生了什么

  1. DNS解析:将域名转换为IP地址。
  2. 建立TCP连接:通过三次握手与服务器建立TCP连接。
  3. 发送HTTP请求:客户端向服务器发送HTTP请求报文。
  4. 服务器处理请求:服务器处理请求并生成响应。
  5. 发送HTTP响应:服务器将响应报文返回给客户端。
  6. 浏览器渲染页面:浏览器解析HTML、CSS、JavaScript等文件,构建DOM树和渲染树,绘制页面。

网络传输如何保证可靠性和安全性

可靠性

  1. TCP协议:通过序列号、确认机制、重传机制和窗口控制实现可靠数据传输。
  2. 错误检测:使用校验和等方法检测并纠正传输错误。
  3. 拥塞控制:避免网络拥塞,提高传输效率。

安全性

  1. 加密:使用TLS/SSL协议加密数据,保护传输过程中的数据安全。
  2. 身份验证:验证通信双方的身份,防止伪装和中间人攻击。
  3. 数据完整性:使用消息摘要算法确保数据在传输过程中未被篡改。

手撕算法:最大连续子数组和(hot 100)

问题描述: 找到一个整数数组的一个连续子数组,使得该子数组的和最大,并返回这个最大和。

示例代码(Java)

public int maxSubArray(int[] nums) {
    int maxSoFar = nums[0];
    int maxEndingHere = nums[0];
    for (int i = 1; i < nums.length; i++) {
        maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]);
        maxSoFar = Math.max(maxSoFar, maxEndingHere);
    }
    return maxSoFar;
}

解释

  1. 初始化maxSoFarmaxEndingHere 都初始化为数组的第一个元素。
  2. 迭代:遍历数组,对于每个元素,更新 maxEndingHere 为当前元素和 maxEndingHere 之和的较大值。
  3. 更新最大值:每次都更新 maxSoFarmaxSoFarmaxEndingHere 中的较大值。
  4. 返回结果:返回 maxSoFar 即为最大子数组和。
  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
携程Java校招笔试题主要考察对Java语言的基础知识和应用能力的掌握。下面我将用300字中文回答一道携程Java校招笔试题。 题目描述:有一个包含N个元素的整型数组,数组中的元素可正可负。编写一个函数,返回数组中所包含元素的最大连续子数组的和。 解题思路:这是一道求最大连续子数组和的经典问题,可以使用动态规划的思想解决。 首先,我们定义两个变量max和currentSum,分别用于保存当前的最大连续子数组和和当前元素的和。初始时,将max和currentSum都设置为数组中的第一个元素。 然后,我们从数组的第二个元素开始遍历。对于每个元素,我们将其与之前的currentSum相加,并与该元素本身进行比较。如果大于当前元素,则更新currentSum为这个和,否则,将currentSum设置为当前元素。 同时,我们还需要将currentSum与max进行比较,如果大于max,则更新max为currentSum。这样,每次遍历的时候都会更新最大连续子数组和。 最后,当遍历完整个数组后,max中保存的就是最大连续子数组的和。将其返回即可。 代码示例: ```java public int maxSubArraySum(int[] nums) { int max = nums[0]; int currentSum = nums[0]; for (int i = 1; i < nums.length; i++) { currentSum = Math.max(currentSum + nums[i], nums[i]); max = Math.max(max, currentSum); } return max; } ``` 这个函数的时间复杂度是O(N),其中N是数组的长度。 通过以上的解题思路和示例代码,我们可以在面试中灵活应用,解决类似的最大连续子数组和的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓宜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值