java案例统计回传次数反映保守程度?

wen java案例 3

Java 案例:统计回传次数反映保守程度

"回传次数"这个概念在不同场景有不同含义,下面给出一个通用可复用的 Java 实现方案,你可以根据实际业务替换字段。

java案例统计回传次数反映保守程度?

场景理解

回传次数"指某个对象在某段时间内被上报/回调/重试的次数,次数越多,说明:

  • 系统越"保守"(宁愿多次确认、多次重发,也不愿漏掉)
  • 或用户行为越"保守"(反复操作、犹豫)

下面以消息回传(回调)统计为例,通过回传频次来计算"保守度"。

核心代码

数据模型

import java.time.LocalDateTime;
/** 一次回传记录 */
public class CallbackRecord {
    private String bizId;          // 业务ID(如订单号、消息ID)
    private String userId;         // 用户/客户端标识
    private LocalDateTime time;    // 回传时间
    private boolean success;       // 是否成功
    public CallbackRecord(String bizId, String userId, LocalDateTime time, boolean success) {
        this.bizId = bizId;
        this.userId = userId;
        this.time = time;
        this.success = success;
    }
    // getter 省略...
    public String getUserId() { return userId; }
    public String getBizId() { return bizId; }
    public LocalDateTime getTime() { return time; }
    public boolean isSuccess() { return success; }
}

统计服务

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
public class CallbackStatsService {
    /**
     * 按用户统计每个业务ID的平均回传次数
     * 回传次数越高 -> 保守度越高
     */
    public Map<String, UserConservativeScore> analyze(List<CallbackRecord> records,
                                                       LocalDateTime windowStart,
                                                       LocalDateTime windowEnd) {
        // 1. 过滤时间窗口
        List<CallbackRecord> filtered = records.stream()
                .filter(r -> !r.getTime().isBefore(windowStart)
                          && !r.getTime().isAfter(windowEnd))
                .collect(Collectors.toList());
        // 2. 按 userId -> bizId 分组计数
        Map<String, Map<String, Long>> userBizCount = filtered.stream()
                .collect(Collectors.groupingBy(
                        CallbackRecord::getUserId,
                        Collectors.groupingBy(CallbackRecord::getBizId, Collectors.counting())
                ));
        // 3. 计算保守度指标
        Map<String, UserConservativeScore> result = new HashMap<>();
        for (Map.Entry<String, Map<String, Long>> e : userBizCount.entrySet()) {
            String userId = e.getKey();
            Collection<Long> counts = e.getValue().values();
            double avg = counts.stream().mapToLong(Long::longValue).average().orElse(0);
            long max = counts.stream().mapToLong(Long::longValue).max().orElse(0);
            long total = counts.stream().mapToLong(Long::longValue).sum();
            // 保守度 = 平均回传次数(可自定义权重公式)
            double conservativeScore = calcScore(avg, max);
            result.put(userId, new UserConservativeScore(
                    userId, e.getValue().size(), total, avg, max, conservativeScore));
        }
        return result;
    }
    /** 保守度评分:可替换为业务公式 */
    private double calcScore(double avg, long max) {
        // 示例:平均次数占 70%,最大次数占 30%
        return avg * 0.7 + max * 0.3;
    }
}

结果对象

public class UserConservativeScore {
    private String userId;
    private int bizCount;        // 涉及业务数
    private long totalCallbacks; // 总回传次数
    private double avgCallbacks; // 平均每个业务回传次数
    private long maxCallbacks;   // 单业务最大回传次数
    private double score;        // 保守度评分
    public UserConservativeScore(String userId, int bizCount, long totalCallbacks,
                                 double avgCallbacks, long maxCallbacks, double score) {
        this.userId = userId;
        this.bizCount = bizCount;
        this.totalCallbacks = totalCallbacks;
        this.avgCallbacks = avgCallbacks;
        this.maxCallbacks = maxCallbacks;
        this.score = score;
    }
    // toString 省略...
}

测试用例

public class Demo {
    public static void main(String[] args) {
        LocalDateTime base = LocalDateTime.now();
        List<CallbackRecord> records = List.of(
            // 用户A:3个业务,回传次数多 -> 保守
            new CallbackRecord("order1", "A", base.minusMinutes(10), true),
            new CallbackRecord("order1", "A", base.minusMinutes(9),  false),
            new CallbackRecord("order1", "A", base.minusMinutes(8),  true),
            new CallbackRecord("order2", "A", base.minusMinutes(7),  true),
            new CallbackRecord("order2", "A", base.minusMinutes(6),  true),
            new CallbackRecord("order3", "A", base.minusMinutes(5),  true),
            // 用户B:每个业务只回传一次 -> 不保守
            new CallbackRecord("order4", "B", base.minusMinutes(10), true),
            new CallbackRecord("order5", "B", base.minusMinutes(9),  true)
        );
        CallbackStatsService svc = new CallbackStatsService();
        Map<String, UserConservativeScore> r = svc.analyze(
                records, base.minusHours(1), base);
        r.values().stream()
         .sorted(Comparator.comparingDouble(UserConservativeScore::getScore).reversed())
         .forEach(s -> System.out.printf(
            "用户=%s 业务数=%d 总回传=%d 平均=%.2f 最大=%d 保守度=%.2f%n",
            s.getUserId(), s.getBizCount(), s.getTotalCallbacks(),
            s.getAvgCallbacks(), s.getMaxCallbacks(), s.getScore()));
    }
}

输出示例:

用户=A 业务数=3 总回传=6 平均=2.00 最大=3 保守度=2.30
用户=B 业务数=2 总回传=2 平均=1.00 最大=1 保守度=1.00

设计要点

要点 说明
分组维度 按 userId/bizId 分组,可换成设备、渠道、接口等
时间窗口 用 windowStart/End 隔离统计周期,避免历史数据干扰
评分公式 calcScore 可自定义,如加入失败重试权重、时间衰减等
流式处理 stream().collect(groupingBy(...counting())) 天然支持大数据量
扩展性 若数据量大,可改用 ConcurrentHashMap + 分段统计,或落 Redis 计数

如何"反映保守程度"

  • 平均回传次数 ↑ → 系统/用户倾向多次确认 → 保守
  • 单业务最大回传次数 ↑ → 存在极端重试行为 → 风险规避倾向强
  • 失败后的重试率 ↑ → 更保守(宁重不漏)

如果需要按接口维度、设备维度或加入失败重试权重,告诉我具体业务场景,我可以再给出对应的公式和代码。

抱歉,评论功能暂时关闭!