中通笔试ShowMeBug编程题复盘

发布于:2025-09-04 ⋅ 阅读:(21) ⋅ 点赞:(0)

第一题

需求:根据示例数据完成如下功能
1. 统计每个用户的订单数量
2. 统计每个用户消费金额
3. 统计订单数量最多的用户
4. 统计消费金额最多的用户
5. 根据用户id统计该用户的订单

Order类

package com.mmg;

public class Order {
    public String userId;
    public String orderId;
    public double amount;

    public Order(String userId, String orderId, double amount) {
        this.userId = userId;
        this.orderId = orderId;
        this.amount = amount;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    @Override
    public String toString() {
        return "Order{" +
                "userId='" + userId + '\'' +
                ", orderId='" + orderId + '\'' +
                ", amount=" + amount +
                '}';
    }
}

SimpleTest

package com.mmg;

import java.util.*;

/**
 * 需求:
 * 1. 统计每个用户的订单数量
 * 2. 统计每个用户消费金额
 * 3. 统计订单数量最多的用户
 * 4. 统计消费金额最多的用户
 * 5. 根据用户id统计该用户的订单
 */
public class Test {
    public static void main(String[] args) {
        // 示例订单数据
        List<Order> orders = Arrays.asList(
                new Order("user1", "order1", 100),
                new Order("user1", "order2", 200),
                new Order("user2", "order3", 300),
                new Order("user3", "order4", 100)
        );

        // 1. 统计每个用户的订单数量
        Map<String, Integer> stringIntegerMap = countOrdersByUser(orders);
        System.out.println(stringIntegerMap);

        // 2. 统计每个用户消费金额
        Map<String, Double> stringDoubleMap = sumAmountByUser(orders);
        System.out.println(stringDoubleMap);

        // 3. 统计订单数量最多的用户
        String maxOrderUser = getMaxOrderUser(stringIntegerMap);
        System.out.println("订单数量最多的用户: " + maxOrderUser);

        // 4. 统计消费金额最多的用户
        String maxAmountUser = getMaxAmountUser(stringDoubleMap);
        System.out.println("消费金额最多的用户: " + maxAmountUser);

        // 5. 根据用户id统计该用户的订单
        List<Order> ordersByUserId = getOrdersByUserId(orders, "user1");
        System.out.println(ordersByUserId);
    }

    // 1. 统计每个用户的订单数量
    public static Map<String, Integer> countOrdersByUser(List<Order> orders) {
        Map<String, Integer> countMap = new HashMap<>();
        orders.forEach(order -> {
            String userId = order.getUserId();
            countMap.put(userId, countMap.getOrDefault(userId, 0) + 1);
        });
        return countMap;
    }

    // 2. 统计每个用户消费金额
    public static Map<String, Double> sumAmountByUser(List<Order> orders) {
        Map<String, Double> amountMap = new HashMap<>();
        orders.forEach(order -> {
            String userId = order.getUserId();
            double amount = order.getAmount();
            amountMap.put(userId, amountMap.getOrDefault(userId, 0.00) + amount);
        });
        return amountMap;
    }

    // 3. 统计订单数量最多的用户
    public static String getMaxOrderUser(Map<String, Integer> countMap) {
        String maxUser = null;
        int maxCount = 0;
        for (Map.Entry<String, Integer> entry : countMap.entrySet()) {
            if (entry.getValue() > maxCount) {
                maxCount = entry.getValue();
                maxUser = entry.getKey();
            }
        }
        return maxUser;
    }

    // 4. 统计消费金额最多的用户
    public static String getMaxAmountUser(Map<String, Double> amountMap) {
        String maxUser = null;
        double maxAmount = 0;
        for (Map.Entry<String, Double> entry : amountMap.entrySet()) {
            if (entry.getValue() > maxAmount) {
                maxAmount = entry.getValue();
                maxUser = entry.getKey();
            }
        }
        return maxUser;
    }

    // 5. 根据用户id统计该用户的订单
    public static List<Order> getOrdersByUserId(List<Order> orders, String userId) {
        List<Order> orderList = new ArrayList<>();
        orders.forEach(order -> {
            if (userId.equals(order.getUserId())) {
                orderList.add(order);
            }
        });
        return orderList;
    }
}

第二题

需求:使用多线程完成以下消费者-生产者案例

package com.mmg;

/**
 * 生产者-消费者案例
 */
public class Test02 {
    public static void main(String[] args) {
        // 创建容量为10的仓库
        Test02 warehouse = new Test02(10);

        // 1. 生产者线程:每次生产3个面包,生产5次
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 5; i++) {
                    int produceCount = 3;
                    warehouse.produceBread(produceCount);
                    System.out.println("【生产者】生产 " + produceCount + " 个面包,当前库存:" + warehouse.getCurrentStock());
                    Thread.sleep(500); // 模拟生产耗时
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("生产者线程被中断");
            }
        }, "生产者线程");

        // 2. 消费者线程:每次消费2个面包,消费8次
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 8; i++) {
                    int consumeCount = 2;
                    warehouse.consumeBread(consumeCount);
                    System.out.println("【消费者】消费 " + consumeCount + " 个面包,当前库存:" + warehouse.getCurrentStock());
                    Thread.sleep(800); // 模拟消费耗时
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("消费者线程被中断");
            }
        }, "消费者线程");

        // 启动线程
        producer.start();
        consumer.start();
    }

    private final int capacity;    // 仓库容量(final修饰,初始化后不可变)
    private int currentStock;      // 当前库存(线程共享变量,需同步保护)

    // 构造方法:初始化仓库容量和初始库存(初始库存为0)
    public Test02(int capacity) {
        this.capacity = capacity;
        this.currentStock = 0;
    }

    /**
     * 生产者方法:生产指定数量的面包
     * @param count 生产数量(需大于0)
     * @throws InterruptedException 线程等待被中断时抛出
     */
    public synchronized void produceBread(int count) throws InterruptedException {
        // 1. 合法性校验:生产数量不能为负数或0
        if (count <= 0) {
            throw new IllegalArgumentException("生产数量必须大于0!");
        }

        // 2. 等待仓库有足够空间(若当前库存+生产数量 > 容量,需等待)
        // 用while而非if:防止线程被"虚假唤醒"(唤醒后需重新检查条件)
        while (currentStock + count > capacity) {
            System.out.println("【等待生产】当前库存:" + currentStock + ",生产" + count + "个后将超出容量" + capacity + ",等待消费者消费...");
            this.wait(); // 释放锁,进入等待队列,直到被notifyAll()唤醒
        }

        // 3. 执行生产逻辑:更新当前库存
        currentStock += count;

        // 4. 唤醒等待的消费者(生产后库存增加,可能有消费者在等库存)
        this.notifyAll();
    }

    /**
     * 消费者方法:消费指定数量的面包
     * @param count 消费数量(需大于0)
     * @throws InterruptedException 线程等待被中断时抛出
     */
    public synchronized void consumeBread(int count) throws InterruptedException {
        // 1. 合法性校验:消费数量不能为负数或0
        if (count <= 0) {
            throw new IllegalArgumentException("消费数量必须大于0!");
        }

        // 2. 等待仓库有足够库存(若当前库存 < 消费数量,需等待)
        while (currentStock < count) {
            System.out.println("【等待消费】当前库存:" + currentStock + ",不足消费" + count + "个,等待生产者生产...");
            this.wait(); // 释放锁,进入等待队列,直到被notifyAll()唤醒
        }

        // 3. 执行消费逻辑:更新当前库存
        currentStock -= count;

        // 4. 唤醒等待的生产者(消费后库存减少,可能有生产者在等空间)
        this.notifyAll();
    }

    // 获取当前库存(同步方法,保证线程读取到最新值)
    public synchronized int getCurrentStock() {
        return currentStock;
    }

    // 获取仓库剩余空间(同步方法,保证计算基于最新库存)
    public synchronized int getRemainingSpace() {
        return capacity - currentStock;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到