高频面试问题详解

一、基础问题
  1. HashMap扩容机制

    • 触发条件:当元素数量超过 容量 * 负载因子(默认0.75) 时触发扩容。
    • 扩容过程
      1. 新容量为旧容量的2倍(如16 → 32)。
      2. 遍历旧数组,重新计算每个元素的哈希值,分配到新数组的对应位置。
      3. Java 8优化:链表长度≥8时转为红黑树,提高查询效率。
    • 示例
      HashMap<Integer, String> map = new HashMap<>(16);
      // 当插入第13个元素(16*0.75=12)时触发扩容
      for (int i = 0; i < 13; i++) {
          map.put(i, "value" + i);
      }
      

  2. Spring循环依赖解决

    • 三级缓存机制
      • singletonObjects:完整Bean实例。
      • earlySingletonObjects:提前暴露的原始Bean(未填充属性)。
      • singletonFactories:Bean工厂,用于生成代理对象(如AOP场景)。
    • 流程
      1. Bean A实例化后,放入三级缓存(singletonFactories)。
      2. 填充A的属性时发现依赖Bean B,触发B的实例化。
      3. B填充属性时从三级缓存获取A的工厂,生成A的代理对象。
      4. B初始化完成后,A完成属性填充。
    • 限制:仅支持Setter注入,构造器注入无法解决循环依赖。

二、设计题
  1. 短链系统设计

    • 核心组件
      • 发号器:使用Snowflake算法生成唯一ID,转换为Base62短码(如 https://s.com/abc123)。
      • 缓存层:Redis缓存热点短链(Key:短码,Value:原始URL),过期时间24小时。
      • 存储层:MySQL分库分表(按短码哈希分片),字段包括 short_codeorigin_urlexpire_time
    • 高并发处理
      • 布隆过滤器拦截无效短码查询。
      • 异步写入数据库(MQ削峰)。
  2. 微信红包架构

    • 预分配金额
      • 二倍均值算法:剩余金额为M,剩余人数为N,每次分配金额范围为 [1, 2M/N)
      def allocate_red_packet(total_amount, num):
          result = []
          for i in range(num-1):
              avg = total_amount / (num - i) * 2
              money = random.uniform(0.01, avg)
              result.append(round(money, 2))
              total_amount -= money
          result.append(round(total_amount, 2))
          return result
      

    • 抢红包流程
      1. 用户抢红包时,Redis原子操作扣减预分配金额(DECRBY)。
      2. 记录明细到分库分表(按用户ID哈希)。
    • 防超发:数据库唯一索引(红包ID + 用户ID) + 异步对账任务。

三、算法问题
  1. Top K问题(堆排序)

    • 步骤
      1. 构建大小为K的小顶堆。
      2. 遍历数组,若元素 > 堆顶,替换堆顶并调整堆。
      3. 最终堆中元素即为Top K。
    • 时间复杂度:O(n log K)。
    • 代码示例
      public int[] topK(int[] nums, int k) {
          PriorityQueue<Integer> heap = new PriorityQueue<>();
          for (int num : nums) {
              if (heap.size() < k) {
                  heap.offer(num);
              } else if (num > heap.peek()) {
                  heap.poll();
                  heap.offer(num);
              }
          }
          return heap.stream().mapToInt(i -> i).toArray();
      }
      

  2. LRU缓存(LinkedHashMap)

    • 实现原理
      • 继承 LinkedHashMap,设置 accessOrder=true,使最近访问的元素移至链表尾部。
      • 重写 removeEldestEntry 方法,当容量超限时移除链表头部元素。
    • 代码示例
      class LRUCache<K, V> extends LinkedHashMap<K, V> {
          private final int capacity;
      
          public LRUCache(int capacity) {
              super(capacity, 0.75f, true);
              this.capacity = capacity;
          }
      
          @Override
          protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
              return size() > capacity;
          }
      }
      

    • 优化:线程安全版本需结合 ConcurrentHashMap 和同步锁。

四、总结与扩展
  • HashMap:关注Java 8的红黑树优化和哈希冲突解决策略。
  • Spring循环依赖:理解三级缓存与AOP代理的交互细节。
  • 短链系统:重点设计发号器与高可用存储方案。
  • 微信红包:强调预分配算法和原子扣减逻辑。
  • 算法:掌握堆排序在数据流场景的应用,LRU的变种实现(如LFU)。

通过结合代码示例和架构图,可清晰展示技术深度与系统设计能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值