Java Queue实现类面试题

Java Queue实现类面试题

ArrayDeque

Q1: ArrayDeque的实现原理是什么?

ArrayDeque是基于循环数组实现的双端队列。

public class ArrayDequePrincipleExample {
    // 模拟ArrayDeque的基本实现
    public class SimpleArrayDeque<E> {
        private static final int MIN_INITIAL_CAPACITY = 8;
        private Object[] elements;
        private int head;
        private int tail;
        
        @SuppressWarnings("unchecked")
        public SimpleArrayDeque() {
            elements = new Object[MIN_INITIAL_CAPACITY];
        }
        
        // 从队首添加元素
        public void addFirst(E e) {
            if (e == null) throw new NullPointerException();
            head = (head - 1) & (elements.length - 1);
            elements[head] = e;
            if (head == tail) doubleCapacity();
        }
        
        // 从队尾添加元素
        public void addLast(E e) {
            if (e == null) throw new NullPointerException();
            elements[tail] = e;
            tail = (tail + 1) & (elements.length - 1);
            if (tail == head) doubleCapacity();
        }
        
        // 扩容
        private void doubleCapacity() {
            int p = head;
            int n = elements.length;
            int r = n - p;
            int newCapacity = n << 1;
            Object[] a = new Object[newCapacity];
            System.arraycopy(elements, p, a, 0, r);
            System.arraycopy(elements, 0, a, r, p);
            elements = a;
            head = 0;
            tail = n;
        }
    }
}

Q2: ArrayDeque相比LinkedList有什么优势?

public class ArrayDequeVsLinkedListExample {
    public void comparePerformance() {
        ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
        LinkedList<Integer> linkedList = new LinkedList<>();
        int n = 1000000;
        
        // 1. 添加性能对比
        long start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            arrayDeque.addLast(i);
        }
        System.out.println("ArrayDeque添加耗时:" + (System.currentTimeMillis() - start));
        
        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            linkedList.addLast(i);
        }
        System.out.println("LinkedList添加耗时:" + (System.currentTimeMillis() - start));
        
        // 2. 随机访问性能对比
        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            arrayDeque.contains(i);
        }
        System.out.println("ArrayDeque查找耗时:" + (System.currentTimeMillis() - start));
        
        start = System.currentTimeMillis();
        for (int i = 0; i < n; i++) {
            linkedList.contains(i);
        }
        System.out.println("LinkedList查找耗时:" + (System.currentTimeMillis() - start));
    }
}

PriorityQueue

Q3: PriorityQueue的实现原理是什么?

PriorityQueue是基于堆(最小堆)实现的优先级队列。

public class PriorityQueuePrincipleExample {
    // 1. 自然排序
    public void naturalOrdering() {
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        pq.offer(3);
        pq.offer(1);
        pq.offer(2);
        while (!pq.isEmpty()) {
            System.out.println(pq.poll()); // 输出1,2,3
        }
    }
    
    // 2. 自定义排序
    public void customOrdering() {
        PriorityQueue<Person> pq = new PriorityQueue<>((p1, p2) -> {
            int ageCompare = Integer.compare(p1.getAge(), p2.getAge());
            if (ageCompare != 0) return ageCompare;
            return p1.getName().compareTo(p2.getName());
        });
        
        pq.offer(new Person("Tom", 20));
        pq.offer(new Person("Jerry", 18));
        pq.offer(new Person("Bob", 20));
    }
    
    // 3. 堆操作示例
    public void heapOperations() {
        PriorityQueue<Integer> pq = new PriorityQueue<>();
        // 添加元素(上浮)
        pq.offer(5);
        pq.offer(2);
        pq.offer(8);
        
        // 删除元素(下沉)
        int min = pq.poll();  // 获取并删除最小元素
        
        // 查看最小元素
        int peek = pq.peek(); // 只查看不删除
    }
}

BlockingQueue

Q4: BlockingQueue的特点和实现类有哪些?

public class BlockingQueueExample {
    // 1. ArrayBlockingQueue示例
    public void arrayBlockingQueueDemo() {
        ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
        
        // 生产者线程
        new Thread(() -> {
            try {
                queue.put("1");  // 阻塞式添加
                queue.put("2");
                queue.put("3");
                queue.put("4");  // 队列满,阻塞
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        
        // 消费者线程
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                System.out.println(queue.take());  // 阻塞式获取
                System.out.println(queue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
    
    // 2. LinkedBlockingQueue示例
    public void linkedBlockingQueueDemo() {
        LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
        // 无界队列,默认容量Integer.MAX_VALUE
        
        // 添加元素的不同方法
        queue.add("1");     // 队列满时抛出异常
        queue.offer("2");   // 队列满时返回false
        try {
            queue.put("3"); // 队列满时阻塞
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    // 3. DelayQueue示例
    public static class DelayedElement implements Delayed {
        private final String data;
        private final long delayTime;
        
        public DelayedElement(String data, long delay) {
            this.data = data;
            this.delayTime = System.currentTimeMillis() + delay;
        }
        
        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(delayTime - System.currentTimeMillis(), 
                              TimeUnit.MILLISECONDS);
        }
        
        @Override
        public int compareTo(Delayed o) {
            return Long.compare(getDelay(TimeUnit.MILLISECONDS), 
                              o.getDelay(TimeUnit.MILLISECONDS));
        }
    }
    
    public void delayQueueDemo() {
        DelayQueue<DelayedElement> queue = new DelayQueue<>();
        queue.offer(new DelayedElement("1", 1000));  // 延迟1秒
        queue.offer(new DelayedElement("2", 2000));  // 延迟2秒
        
        try {
            System.out.println(queue.take().data);  // 1秒后输出"1"
            System.out.println(queue.take().data);  // 2秒后输出"2"
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Q5: 如何选择合适的Queue实现类?

public class QueueSelectionExample {
    public void demonstrateUsage() {
        // 1. 一般用途,双端队列
        Deque<String> arrayDeque = new ArrayDeque<>();
        
        // 2. 需要优先级排序
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
        
        // 3. 固定大小,线程安全
        BlockingQueue<String> arrayBlockingQueue = 
            new ArrayBlockingQueue<>(10);
        
        // 4. 无界,线程安全
        BlockingQueue<String> linkedBlockingQueue = 
            new LinkedBlockingQueue<>();
        
        // 5. 延迟队列
        DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();
        
        // 6. 优先级阻塞队列
        BlockingQueue<String> priorityBlockingQueue = 
            new PriorityBlockingQueue<>();
    }
    
    // 使用场景示例
    public void usageScenarios() {
        // 1. 实现栈
        Deque<String> stack = new ArrayDeque<>();
        stack.push("A");
        stack.pop();
        
        // 2. 任务优先级排序
        PriorityQueue<Task> taskQueue = new PriorityQueue<>(
            (t1, t2) -> Integer.compare(t2.getPriority(), t1.getPriority())
        );
        
        // 3. 生产者-消费者模式
        BlockingQueue<String> messageQueue = new ArrayBlockingQueue<>(100);
        // 生产者线程
        new Thread(() -> {
            try {
                messageQueue.put("message");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
        // 消费者线程
        new Thread(() -> {
            try {
                String message = messageQueue.take();
                process(message);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
    
    private void process(String message) {
        // 处理消息
    }
}

Q6: 并发队列的性能考虑

public class ConcurrentQueuePerformanceExample {
    // 1. 不同并发队列的性能对比
    public void comparePerformance() {
        int n = 100000;
        
        // ArrayBlockingQueue
        BlockingQueue<Integer> abq = new ArrayBlockingQueue<>(n);
        testQueue("ArrayBlockingQueue", abq, n);
        
        // LinkedBlockingQueue
        BlockingQueue<Integer> lbq = new LinkedBlockingQueue<>();
        testQueue("LinkedBlockingQueue", lbq, n);
        
        // ConcurrentLinkedQueue
        Queue<Integer> clq = new ConcurrentLinkedQueue<>();
        testQueue("ConcurrentLinkedQueue", clq, n);
    }
    
    private void testQueue(String name, Queue<Integer> queue, int n) {
        long start = System.currentTimeMillis();
        // 多线程添加元素
        Thread[] producers = new Thread[4];
        for (int i = 0; i < producers.length; i++) {
            producers[i] = new Thread(() -> {
                for (int j = 0; j < n/4; j++) {
                    queue.offer(j);
                }
            });
            producers[i].start();
        }
        
        // 等待所有生产者完成
        for (Thread producer : producers) {
            try {
                producer.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        
        System.out.println(name + " 耗时:" + 
                          (System.currentTimeMillis() - start));
    }
}

面试关键点

  1. 理解ArrayDeque的循环数组实现
  2. 掌握PriorityQueue的堆实现
  3. 了解BlockingQueue的特点和实现类
  4. 熟悉不同队列的使用场景
  5. 掌握并发队列的性能特点
  6. 理解阻塞队列的工作原理
  7. 注意队列的边界条件处理
  8. 掌握队列的选择原则

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

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

相关文章

Hadoop初体验

一、HDFS初体验 1. shell命令操作 hadoop fs -mkdir /itcast hadoop fs -put zookeeper.out /itcast hadoop fs -ls / 2. Web UI页面操作 结论&#xff1a; HDFS本质就是一个文件系统有目录树结构 和Linux类似&#xff0c;分文件、文件夹为什么上传一个小文件也这…

机器学习基础入门——机器学习库介绍(NumPy、pandas、Matplotlib)

机器学习库介绍&#xff08;NumPy、pandas、Matplotlib&#xff09; 在 Python 机器学习的领域中&#xff0c;NumPy、pandas 和 Matplotlib 是三个不可或缺的基础库。它们分别在数值计算、数据处理与分析以及数据可视化方面发挥着关键作用&#xff0c;极大地提升了开发效率与数…

Redis——用户签到BitMap,UV统计

目录 BitMap 使用场景 1. 用户签到系统 2. 用户行为标记 3. 布隆过滤器&#xff08;Bloom Filter&#xff09; BitMap介绍 Redis中的使用 Redis功能示例 添加&#xff1a; 获取&#xff1a; 批量获取&#xff1a; java中实现 统计本月连续签到次数 UV统计 UV 统计…

【数据结构】(12) 反射、枚举、lambda 表达式

一、反射 1、反射机制定义及作用 反射是允许程序在运行时检查和操作类、方法、属性等的机制&#xff0c;能够动态地获取信息、调用方法等。换句话说&#xff0c;在编写程序时&#xff0c;不需要知道要操作的类的具体信息&#xff0c;而是在程序运行时获取和使用。 2、反射机制…

【初探数据结构】时间复杂度和空间复杂度

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对数据结构感…

基于 MySQL 递归 CTE 实现表,父级id与子级id拼接

1、函数 xr_test.tb_content替换成自己的表 CREATE DEFINERroot% FUNCTION get_related_ids(start_id BIGINT) RETURNS varchar(1000) CHARSET utf8mb4 COLLATE utf8mb4_general_ciDETERMINISTIC BEGINDECLARE result_ids VARCHAR(1000);-- 使用递归 CTE 查找所有相关的 idWI…

Redission可重试、超时续约的实现原理(源码分析)

Redission遇到其他进程已经占用资源的时候会在指定时间waitTime内进行重试。实现过程如下&#xff1a; 执行获取锁的lua脚本时&#xff0c;会返回一个值&#xff0c; 如果获取锁成功&#xff0c;返回nil&#xff0c;也就是java里的null 如果获取锁失败&#xff0c;用语句“PT…

ue----git局域网内部署裸仓库,别的机器进行访问

最近由于经常迁移项目到另一台机器上进行部署更新一点就要整个迁移 弄得麻烦了 就在网上学了一下这个方式 首先我们在想要建立裸仓库的电脑上找到一个文件夹放置我们的裸仓库 在此点击鼠标右键选择 open git bash here 输入命令 创裸仓库 git init --bare gitTestName.git…

输入搜索、分组展示选项、下拉选取,el-select 实现:即输入关键字检索,返回分组选项,选取跳转到相应内容页 —— VUE 项目-全局模糊检索

后端数据代码写于下一篇&#xff1a;输入搜索、分组展示选项、下拉选取&#xff0c;全局跳转页&#xff0c;el-select 实现 —— 后端数据处理代码&#xff0c;抛砖引玉展思路 【效果图】&#xff1a;分组展示选项 >【提供界面操作体验】 【录制效果视频展示】&#xff1a…

【UCB CS 61B SP24】Lecture 11 - Inheritance 4: Iterators, Object Methods学习笔记

本文内容为集合&#xff08;Set&#xff09;的介绍与使用&#xff0c;并通过数组手动实现集合&#xff0c;接着介绍了迭代器&#xff0c;使用迭代器我们能够更方便地遍历集合中的元素。 1. Set 1.1 Set介绍与Java实现类的使用 集合&#xff08;Set&#xff09;是一种常见的数…

玩机日记 12 fnOS使用lucky反代https转发到外网提供服务

目录 1、安装lucky 2、更新lucky 3、上传ssl证书 4、设置安全入口&#xff0c;替换fnOS的应用url 5、添加https反代 这一篇主要是解决一下飞牛反代https的问题。可以先看玩机日记 12.5 在PVE Windows11上部署本地AI模型&#xff0c;使用群晖反代https转发到外网提供服务&a…

神经网络八股(3)

1.什么是梯度消失和梯度爆炸 梯度消失是指梯度在反向传播的过程中逐渐变小&#xff0c;最终趋近于零&#xff0c;这会导致靠前层的神经网络层权重参数更新缓慢&#xff0c;甚至不更新&#xff0c;学习不到有用的特征。 梯度爆炸是指梯度在方向传播过程中逐渐变大&#xff0c;…

【ARM】MDK如何生成指定大小的bin文件,并指定空区域的填充数据

1、 文档目标 解决MDK如何生成指定大小的bin文件&#xff0c;并指定空区域的填充数据 2、 问题场景 客户有这样的需求&#xff0c;客户本身的工程编译生成bin文件后&#xff0c;bin文件大小为200k。整体芯片的内存有512k。客户想要最终生成的bin文件可以达到512k的一个情况&a…

Linux-----进程间通信

一、按通信范围分类 同一主机进程通信 传统IPC方式&#xff1a; 管道&#xff08;无名管道、有名管道&#xff09;信号&#xff08;Signal&#xff09; System V IPC&#xff1a; 共享内存&#xff08;效率最高&#xff09;消息队列信号量 POSIX IPC&#xff08;较新标准&#…

Part 3 第十二章 单元测试 Unit Testing

概述 第十二章围绕单元测试展开&#xff0c;阐述了单元测试的实践与重要性&#xff0c;通过对比其他测试类型&#xff0c;突出其特点&#xff0c;还介绍了单元测试的最佳实践、避免的反模式以及与测试替身相关的内容&#xff0c;为编写高质量单元测试提供指导。 章节概要 1…

Windows10配置C++版本的Kafka,并进行发布和订阅测试

配置的环境为&#xff1a;Release x64下的环境 完整项目&#xff1a;https://gitee.com/jiajingong/kafka-publisher 1、首先下载相应的库文件&#xff08;.lib&#xff0c;.dll&#xff09; 参考链接&#xff1a; GitHub - eStreamSoftware/delphi-kafka GitHub - cloade…

Deepseek引爆AI热潮 防静电地板如何守护数据中心安全

近期&#xff0c;Deepseek的爆火将人工智能推向了新的高度&#xff0c;也引发了人们对AI背后基础设施的关注。作为AI运行的“大脑”&#xff0c;数据中心承载着海量数据的存储、处理和传输&#xff0c;其安全稳定运行至关重要。而在这背后&#xff0c;防静电地板扮演着不可或缺…

Spring框架基本使用(Maven详解)

前言&#xff1a; 当我们创建项目的时候&#xff0c;第一步少不了搭建环境的相关准备工作。 那么如果想让我们的项目做起来方便快捷&#xff0c;应该引入更多的管理工具&#xff0c;帮我们管理。 Maven的出现帮我们大大解决了管理的难题&#xff01;&#xff01; Maven&#xf…

QSplashScreen --软件启动前的交互

目录 QSplashScreen 类介绍 使用方式 项目中使用 THPrinterSplashScreen头文件 THPrinterSplashScreen实现代码 使用代码 使用效果 QSplashScreen 类介绍 QSplashScreen 是 Qt 中的一个类&#xff0c;用于显示启动画面。它通常在应用程序启动时显示&#xff0c;以向用户显…

【Vscode 使用】集合1

一、使用make工具管理工程 windows下&#xff0c;下载mingw64&#xff0c;配置好mingw64\bin 为 Win10系统全局变量后。 在mingw64/bin目录下找到mingw32-make.exe工具。复制一份改名为&#xff1a;make.exe&#xff0c;没错&#xff0c;就是那么简单&#xff0c;mingw64自带m…