统计参考ArrayList中TCP Flow对象在已完成流ArrayList的出现频率
实现方案
你的原始嵌套循环方案时间复杂度为O(n*m),当两个列表数据量较大时性能会很差,更高效的方案是通过哈希表预统计已完成流的出现频率,时间复杂度可降低至O(n+m),有两种常用实现方式:
方案1:重写Flow类的equals和hashCode方法(推荐)
因为TCP流通过四元组destIp、sourceIp、destPort、srcPort唯一标识,直接基于这四个字段重写两个方法:
import java.util.Objects; public class Flow { String destIp; String sourceIp; String destPort; String srcPort; double arrivalTime; int completed; // 重写equals方法,仅比对四元组字段 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Flow flow = (Flow) o; return Objects.equals(destIp, flow.destIp) && Objects.equals(sourceIp, flow.sourceIp) && Objects.equals(destPort, flow.destPort) && Objects.equals(srcPort, flow.srcPort); } // 重写hashCode方法,仅基于四元组生成哈希值 @Override public int hashCode() { return Objects.hash(destIp, sourceIp, destPort, srcPort); } }
之后直接用HashMap统计频率即可:
// 第一步:预统计已完成流的出现次数 Map<Flow, Integer> freqMap = new HashMap<>(); for (Flow flow : cList) { freqMap.put(flow, freqMap.getOrDefault(flow, 0) + 1); } // 第二步:遍历参考列表直接取对应频率 for (Flow refFlow : refList) { int count = freqMap.getOrDefault(refFlow, 0); // 此处可对统计结果做后续处理 }
方案2:不修改Flow类,用自定义键统计
如果不能修改原有的Flow类定义,可以把四元组拼接成唯一字符串作为统计的键(注意用IP、端口中不会出现的字符作为分隔符,避免字段内容重合导致键冲突):
Map<String, Integer> freqMap = new HashMap<>(); for (Flow flow : cList) { // 用|作为分隔符拼接四元组,避免键冲突 String key = String.join("|", flow.destIp, flow.sourceIp, flow.destPort, flow.srcPort); freqMap.put(key, freqMap.getOrDefault(key, 0) + 1); } // 遍历参考列表取对应频率 for (Flow refFlow : refList) { String key = String.join("|", refFlow.destIp, refFlow.sourceIp, refFlow.destPort, refFlow.srcPort); int count = freqMap.getOrDefault(key, 0); // 此处可对统计结果做后续处理 }
两种方案都比原始嵌套循环效率高很多,数据量越大性能优势越明显,优先选择方案1,语义更清晰,也不会出现拼接键的冲突风险。
内容的提问来源于stack exchange,提问作者Daniel Larson
相关产品推荐
相关产品推荐

