Java集合应用案例面试题
缓存实现
Q1: 如何使用LinkedHashMap实现LRU缓存?
java
复制代码
public class LRUCacheExample {
// 1. 基于LinkedHashMap实现的LRU缓存
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int capacity;
public LRUCache(int capacity) {
super(capacity, 0.75f, true); // accessOrder = true
this.capacity = capacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > capacity;
}
}
// 2. 线程安全的LRU缓存
public class ConcurrentLRUCache<K, V> {
private final LRUCache<K, V> cache;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public ConcurrentLRUCache(int capacity) {
this.cache = new LRUCache<>(capacity);
}
public V get(K key) {
lock.readLock().lock();
try {
return cache.get(key);
} finally {
lock.readLock().unlock();
}
}
public V put(K key, V value) {
lock.writeLock().lock();
try {
return cache.put(key, value);
} finally {
lock.writeLock().unlock();
}
}
}
// 3. 使用示例
public void demonstrateCache() {
LRUCache<String, String> cache = new LRUCache<>(3);
cache.put("1", "one"); // {1=one}
cache.put("2", "two"); // {1=one, 2=two}
cache.put("3", "three"); // {1=one, 2=two, 3=three}
cache.get("1"); // 访问1,1移到最后
cache.put("4", "four"); // 2被移除,{1=one, 3=three, 4=four}
}
}
消息队列
Q2: 如何实现一个简单的消息队列系统?
java
复制代码
public class MessageQueueExample {
// 1. 消息定义
public class Message {
private String id;
private String content;
private long timestamp;
private int priority;
// 构造方法和getter/setter
}
// 2. 优先级消息队列
public class PriorityMessageQueue {
private final PriorityBlockingQueue<Message> queue;
public PriorityMessageQueue() {
queue = new PriorityBlockingQueue<>(11,
(m1, m2) -> Integer.compare(m2.priority, m1.priority));
}
public void send(Message message) {
queue.offer(message);
}
public Message receive() throws InterruptedException {
return queue.take();
}
}
// 3. 多主题消息系统
public class TopicMessageSystem {
private final ConcurrentHashMap<String, BlockingQueue<Message>> topics;
public TopicMessageSystem() {
topics = new ConcurrentHashMap<>();
}
public void createTopic(String topic) {
topics.putIfAbsent(topic, new LinkedBlockingQueue<>());
}
public void publish(String topic, Message message) {
BlockingQueue<String> queue = topics.get(topic);
if (queue != null) {
queue.offer(message);
}
}
public Message subscribe(String topic) throws InterruptedException {
BlockingQueue<Message> queue = topics.get(topic);
if (queue != null) {
return queue.take();
}
return null;
}
}
}
数据处理
Q3: 如何使用集合框架处理大数据集?
java
复制代码
public class DataProcessingExample {
// 1. 分批处理
public class BatchProcessor<T> {
private final List<T> data;
private final int batchSize;
public BatchProcessor(List<T> data, int batchSize) {
this.data = data;
this.batchSize = batchSize;
}
public void process(Consumer<List<T>> consumer) {
for (int i = 0; i < data.size(); i += batchSize) {
List<T> batch = data.subList(
i, Math.min(i + batchSize, data.size())
);
consumer.accept(batch);
}
}
}
// 2. 并行流处理
public class ParallelProcessor<T> {
private final Collection<T> data;
public ParallelProcessor(Collection<T> data) {
this.data = data;
}
public <R> List<R> process(Function<T, R> mapper) {
return data.parallelStream()
.map(mapper)
.collect(Collectors.toList());
}
public <R> List<R> processWithFilter(
Predicate<T> filter, Function<T, R> mapper) {
return data.parallelStream()
.filter(filter)
.map(mapper)
.collect(Collectors.toList());
}
}
// 3. 使用示例
public void demonstrateProcessing() {
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
numbers.add(i);
}
// 分批处理
BatchProcessor<Integer> batchProcessor =
new BatchProcessor<>(numbers, 1000);
batchProcessor.process(batch -> {
// 处理每一批数据
batch.forEach(System.out::println);
});
// 并行处理
ParallelProcessor<Integer> parallelProcessor =
new ParallelProcessor<>(numbers);
List<Integer> result = parallelProcessor.processWithFilter(
n -> n % 2 == 0, // 过滤偶数
n -> n * 2 // 将数字翻倍
);
}
}
数据结构
Q4: 如何实现常见的数据结构?
java
复制代码
public class DataStructureExample {
// 1. 实现栈
public class Stack<E> {
private final Deque<E> deque = new ArrayDeque<>();
public void push(E element) {
deque.addFirst(element);
}
public E pop() {
return deque.removeFirst();
}
public E peek() {
return deque.peekFirst();
}
public boolean isEmpty() {
return deque.isEmpty();
}
}
// 2. 实现队列
public class Queue<E> {
private final Deque<E> deque = new ArrayDeque<>();
public void enqueue(E element) {
deque.addLast(element);
}
public E dequeue() {
return deque.removeFirst();
}
public E peek() {
return deque.peekFirst();
}
public boolean isEmpty() {
return deque.isEmpty();
}
}
// 3. 实现优先级队列
public class PriorityQueue<E> {
private final java.util.PriorityQueue<E> queue;
public PriorityQueue(Comparator<? super E> comparator) {
this.queue = new java.util.PriorityQueue<>(comparator);
}
public void add(E element) {
queue.offer(element);
}
public E remove() {
return queue.poll();
}
public E peek() {
return queue.peek();
}
}
}
实际应用
Q5: 如何在实际项目中应用集合框架?
java
复制代码
public class RealWorldExample {
// 1. 购物车实现
public class ShoppingCart {
private final Map<Product, Integer> items = new HashMap<>();
public void addItem(Product product, int quantity) {
items.merge(product, quantity, Integer::sum);
}
public void removeItem(Product product, int quantity) {
items.computeIfPresent(product, (k, v) -> {
int newQuantity = v - quantity;
return newQuantity <= 0 ? null : newQuantity;
});
}
public double getTotal() {
return items.entrySet().stream()
.mapToDouble(e -> e.getKey().getPrice() * e.getValue())
.sum();
}
}
// 2. 任务调度系统
public class TaskScheduler {
private final PriorityBlockingQueue<Task> taskQueue;
private final ScheduledExecutorService executor;
public TaskScheduler(int threadCount) {
this.taskQueue = new PriorityBlockingQueue<>();
this.executor = Executors.newScheduledThreadPool(threadCount);
}
public void scheduleTask(Task task) {
taskQueue.offer(task);
executor.schedule(() -> {
Task nextTask = taskQueue.poll();
if (nextTask != null) {
executeTask(nextTask);
}
}, task.getDelay(), TimeUnit.MILLISECONDS);
}
private void executeTask(Task task) {
// 执行任务
}
}
// 3. 缓存系统
public class CacheSystem<K, V> {
private final ConcurrentHashMap<K, V> cache;
private final ScheduledExecutorService cleaner;
public CacheSystem(long cleanupInterval) {
this.cache = new ConcurrentHashMap<>();
this.cleaner = Executors.newSingleThreadScheduledExecutor();
// 定期清理过期数据
cleaner.scheduleAtFixedRate(
this::cleanup,
cleanupInterval,
cleanupInterval,
TimeUnit.MILLISECONDS
);
}
public V get(K key) {
return cache.get(key);
}
public void put(K key, V value) {
cache.put(key, value);
}
private void cleanup() {
// 清理逻辑
}
}
}
Q6: 如何处理高并发场景下的集合操作?
java
复制代码
public class ConcurrentOperationExample {
// 1. 并发计数器
public class ConcurrentCounter {
private final ConcurrentHashMap<String, AtomicLong> counters;
public ConcurrentCounter() {
this.counters = new ConcurrentHashMap<>();
}
public void increment(String key) {
counters.computeIfAbsent(key, k -> new AtomicLong())
.incrementAndGet();
}
public long getCount(String key) {
AtomicLong counter = counters.get(key);
return counter != null ? counter.get() : 0;
}
}
// 2. 并发请求限制器
public class RequestLimiter {
private final ConcurrentHashMap<String, Deque<Long>> requests;
private final int maxRequests;
private final long timeWindow;
public RequestLimiter(int maxRequests, long timeWindow) {
this.requests = new ConcurrentHashMap<>();
this.maxRequests = maxRequests;
this.timeWindow = timeWindow;
}
public boolean isAllowed(String key) {
long now = System.currentTimeMillis();
Deque<Long> times = requests.computeIfAbsent(
key, k -> new ConcurrentLinkedDeque<>()
);
while (!times.isEmpty() && times.getFirst() < now - timeWindow) {
times.removeFirst();
}
if (times.size() < maxRequests) {
times.addLast(now);
return true;
}
return false;
}
}
// 3. 并发缓存
public class ConcurrentCache<K, V> {
private final ConcurrentHashMap<K, V> cache;
private final int maxSize;
public ConcurrentCache(int maxSize) {
this.cache = new ConcurrentHashMap<>();
this.maxSize = maxSize;
}
public V get(K key, Supplier<V> loader) {
return cache.computeIfAbsent(key, k -> {
if (cache.size() >= maxSize) {
// 移除一些缓存项
Iterator<Map.Entry<K, V>> it = cache.entrySet().iterator();
if (it.hasNext()) {
it.next();
it.remove();
}
}
return loader.get();
});
}
}
}
面试关键点
- 理解集合框架在实际应用中的角色
- 掌握不同场景下的集合选择
- 了解并发集合的使用场景
- 熟悉数据处理的最佳实践
- 掌握自定义数据结构的实现
- 理解性能优化的方法
- 注意内存使用和垃圾回收
- 考虑线程安全和并发问题