Collectors.averagingLong()
Collectors.averagingLong() 是专门用于计算长整型(long)数据平均值的收集器,返回结果为 Double 类型。
基本用法
java
// 1. 基本用法 - 计算 Long 列表的平均值
List<Long> numbers = Arrays.asList(100L, 200L, 300L, 400L, 500L);
Double average = numbers.stream()
.collect(Collectors.averagingLong(n -> n));
System.out.println("Average: " + average); // 300.0
// 2. 方法引用简化写法
Double average2 = numbers.stream()
.collect(Collectors.averagingLong(Long::longValue));
// 3. 从 LongStream 直接使用
double longStreamAverage = LongStream.of(100L, 200L, 300L, 400L, 500L)
.average()
.orElse(0.0);
System.out.println("LongStream average: " + longStreamAverage); // 300.0
// 4. 处理大数据(避免溢出)
List<Long> largeNumbers = Arrays.asList(
Long.MAX_VALUE - 1000L,
Long.MAX_VALUE - 2000L,
Long.MAX_VALUE - 3000L
);
Double largeAverage = largeNumbers.stream()
.collect(Collectors.averagingLong(n -> n));
System.out.println("Average of large numbers: " + largeAverage);核心特性
1. 处理大数无溢出
java
// 使用 averagingLong 可以安全处理大数相加
List<Long> veryLargeNumbers = Arrays.asList(
Long.MAX_VALUE,
Long.MAX_VALUE - 1000L,
Long.MAX_VALUE - 2000L
);
// 内部使用双精度浮点数计算,不会溢出
Double average = veryLargeNumbers.stream()
.collect(Collectors.averagingLong(n -> n));
System.out.println("Average of very large numbers: " + average);
// 对比:手动相加可能溢出
try {
long manualSum = veryLargeNumbers.stream().reduce(0L, Long::sum);
System.out.println("Manual sum (may overflow): " + manualSum);
} catch (ArithmeticException e) {
System.out.println("Manual sum overflowed!");
}2. 空流和 null 值处理
java
// 空流返回 0.0
Double emptyAverage = Stream.<Long>empty()
.collect(Collectors.averagingLong(n -> n));
System.out.println("Empty stream average: " + emptyAverage); // 0.0
// 包含 null 值的流
List<Long> withNulls = Arrays.asList(100L, null, 300L, null, 500L);
Double average = withNulls.stream()
.filter(Objects::nonNull)
.collect(Collectors.averagingLong(n -> n));
System.out.println("Average with nulls filtered: " + average); // 300.0
// 提供默认值
Double averageWithDefault = withNulls.stream()
.collect(Collectors.averagingLong(n -> n != null ? n : 0L));
System.out.println("Average with default 0: " + averageWithDefault); // 180.0实际应用示例
示例 1:时间统计
java
class ApiRequest {
private String endpoint;
private long responseTime; // 毫秒
private long requestSize; // 字节
private LocalDateTime timestamp;
public ApiRequest(String endpoint, long responseTime, long requestSize) {
this.endpoint = endpoint;
this.responseTime = responseTime;
this.requestSize = requestSize;
this.timestamp = LocalDateTime.now();
}
// getters
public String getEndpoint() { return endpoint; }
public long getResponseTime() { return responseTime; }
public long getRequestSize() { return requestSize; }
public LocalDateTime getTimestamp() { return timestamp; }
}
public class ApiPerformanceAnalysis {
public static void main(String[] args) {
List<ApiRequest> requests = Arrays.asList(
new ApiRequest("/api/users", 150L, 2048L),
new ApiRequest("/api/users", 200L, 4096L),
new ApiRequest("/api/products", 80L, 1024L),
new ApiRequest("/api/products", 120L, 3072L),
new ApiRequest("/api/orders", 500L, 8192L),
new ApiRequest("/api/orders", 450L, 6144L),
new ApiRequest("/api/users", 180L, 3072L)
);
// 1. 按端点统计平均响应时间
Map<String, Double> avgResponseTimeByEndpoint = requests.stream()
.collect(Collectors.groupingBy(
ApiRequest::getEndpoint,
Collectors.averagingLong(ApiRequest::getResponseTime)
));
System.out.println("Average response time by endpoint (ms):");
avgResponseTimeByEndpoint.forEach((endpoint, avgTime) ->
System.out.printf("%s: %.2f ms%n", endpoint, avgTime));
// /api/users: 176.67 ms
// /api/products: 100.00 ms
// /api/orders: 475.00 ms
// 2. 按端点统计平均请求大小
Map<String, Double> avgSizeByEndpoint = requests.stream()
.collect(Collectors.groupingBy(
ApiRequest::getEndpoint,
Collectors.averagingLong(ApiRequest::getRequestSize)
));
System.out.println("\nAverage request size by endpoint (bytes):");
avgSizeByEndpoint.forEach((endpoint, avgSize) ->
System.out.printf("%s: %.2f bytes%n", endpoint, avgSize));
// 3. 按小时统计平均响应时间
Map<Integer, Double> avgResponseTimeByHour = requests.stream()
.collect(Collectors.groupingBy(
req -> req.getTimestamp().getHour(),
Collectors.averagingLong(ApiRequest::getResponseTime)
));
System.out.println("\nAverage response time by hour:");
avgResponseTimeByHour.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry ->
System.out.printf("%02d:00: %.2f ms%n", entry.getKey(), entry.getValue()));
}
}示例 2:金融数据分析
java
class Transaction {
private String accountId;
private long amount; // 以分为单位(避免浮点数精度问题)
private String type; // "DEPOSIT", "WITHDRAWAL", "TRANSFER"
private LocalDateTime timestamp;
private String category;
public Transaction(String accountId, long amount, String type, String category) {
this.accountId = accountId;
this.amount = amount;
this.type = type;
this.category = category;
this.timestamp = LocalDateTime.now();
}
// getters
public String getAccountId() { return accountId; }
public long getAmount() { return amount; }
public String getType() { return type; }
public String getCategory() { return category; }
public LocalDateTime getTimestamp() { return timestamp; }
// 转换为元
public double getAmountInYuan() {
return amount / 100.0;
}
}
public class FinancialAnalysis {
public static void main(String[] args) {
List<Transaction> transactions = Arrays.asList(
new Transaction("ACC001", 500000L, "DEPOSIT", "SALARY"), // 5000元
new Transaction("ACC001", 150000L, "WITHDRAWAL", "SHOPPING"), // 1500元
new Transaction("ACC002", 1000000L, "DEPOSIT", "INVESTMENT"), // 10000元
new Transaction("ACC001", 250000L, "WITHDRAWAL", "BILLS"), // 2500元
new Transaction("ACC002", 300000L, "WITHDRAWAL", "SHOPPING"), // 3000元
new Transaction("ACC003", 800000L, "DEPOSIT", "SALARY"), // 8000元
new Transaction("ACC001", 200000L, "DEPOSIT", "BONUS"), // 2000元
new Transaction("ACC003", 100000L, "WITHDRAWAL", "ENTERTAINMENT") // 1000元
);
// 1. 按账户统计平均存款金额
Map<String, Double> avgDepositByAccount = transactions.stream()
.filter(t -> "DEPOSIT".equals(t.getType()))
.collect(Collectors.groupingBy(
Transaction::getAccountId,
Collectors.averagingLong(Transaction::getAmount)
));
System.out.println("Average deposit amount by account (分):");
avgDepositByAccount.forEach((accountId, avgAmount) ->
System.out.printf("%s: %.2f 分 (%.2f 元)%n",
accountId, avgAmount, avgAmount / 100.0));
// ACC001: 350000.00 分 (3500.00 元)
// ACC002: 1000000.00 分 (10000.00 元)
// ACC003: 800000.00 分 (8000.00 元)
// 2. 按交易类型统计平均金额
Map<String, Double> avgAmountByType = transactions.stream()
.collect(Collectors.groupingBy(
Transaction::getType,
Collectors.averagingLong(Transaction::getAmount)
));
System.out.println("\nAverage amount by transaction type:");
avgAmountByType.forEach((type, avgAmount) ->
System.out.printf("%s: %.2f 分 (%.2f 元)%n",
type, avgAmount, avgAmount / 100.0));
// 3. 按类别统计平均支出金额
Map<String, Double> avgWithdrawalByCategory = transactions.stream()
.filter(t -> "WITHDRAWAL".equals(t.getType()))
.collect(Collectors.groupingBy(
Transaction::getCategory,
Collectors.averagingLong(Transaction::getAmount)
));
System.out.println("\nAverage withdrawal amount by category:");
avgWithdrawalByCategory.forEach((category, avgAmount) ->
System.out.printf("%s: %.2f 分 (%.2f 元)%n",
category, avgAmount, avgAmount / 100.0));
// 4. 按月统计平均交易金额
Map<YearMonth, Double> avgAmountByMonth = transactions.stream()
.collect(Collectors.groupingBy(
t -> YearMonth.from(t.getTimestamp()),
Collectors.averagingLong(Transaction::getAmount)
));
System.out.println("\nAverage transaction amount by month:");
avgAmountByMonth.forEach((month, avgAmount) ->
System.out.printf("%s: %.2f 元%n",
month, avgAmount / 100.0));
}
}示例 3:文件系统分析
java
class FileInfo {
private String name;
private String extension;
private long size; // 字节
private LocalDateTime lastModified;
private String path;
public FileInfo(String name, String extension, long size, String path) {
this.name = name;
this.extension = extension;
this.size = size;
this.path = path;
this.lastModified = LocalDateTime.now();
}
// getters
public String getName() { return name; }
public String getExtension() { return extension; }
public long getSize() { return size; }
public LocalDateTime getLastModified() { return lastModified; }
public String getPath() { return path; }
}
public class FileSystemAnalysis {
public static void main(String[] args) {
List<FileInfo> files = Arrays.asList(
new FileInfo("document1", "pdf", 2_048_000L, "/docs"),
new FileInfo("presentation", "pptx", 5_120_000L, "/presentations"),
new FileInfo("spreadsheet", "xlsx", 3_072_000L, "/spreadsheets"),
new FileInfo("image1", "jpg", 1_024_000L, "/images"),
new FileInfo("document2", "pdf", 1_536_000L, "/docs"),
new FileInfo("video1", "mp4", 50_000_000L, "/videos"),
new FileInfo("image2", "png", 2_048_000L, "/images"),
new FileInfo("code1", "java", 256_000L, "/code"),
new FileInfo("document3", "docx", 4_096_000L, "/docs"),
new FileInfo("archive1", "zip", 10_240_000L, "/archives")
);
// 1. 按文件类型统计平均文件大小
Map<String, Double> avgSizeByExtension = files.stream()
.collect(Collectors.groupingBy(
FileInfo::getExtension,
Collectors.averagingLong(FileInfo::getSize)
));
System.out.println("Average file size by extension (bytes):");
avgSizeByExtension.forEach((ext, avgSize) ->
System.out.printf("%s: %,.2f bytes (%.2f MB)%n",
ext, avgSize, avgSize / (1024.0 * 1024.0)));
// 2. 按目录统计平均文件大小
Map<String, Double> avgSizeByDirectory = files.stream()
.collect(Collectors.groupingBy(
file -> {
// 提取目录名
String path = file.getPath();
return path.startsWith("/") ? path : "/" + path;
},
Collectors.averagingLong(FileInfo::getSize)
));
System.out.println("\nAverage file size by directory:");
avgSizeByDirectory.forEach((dir, avgSize) ->
System.out.printf("%s: %,.2f bytes%n", dir, avgSize));
// 3. 统计大文件(> 1MB)的平均大小
Double avgLargeFileSize = files.stream()
.filter(file -> file.getSize() > 1_048_576L) // 1 MB
.collect(Collectors.averagingLong(FileInfo::getSize));
System.out.printf("\nAverage size of large files (>1MB): %,.2f bytes%n",
avgLargeFileSize);
// 4. 按文件大小范围分组统计
Map<String, Double> avgSizeByRange = files.stream()
.collect(Collectors.groupingBy(
file -> {
long size = file.getSize();
if (size < 1024) return "小于1KB";
else if (size < 1_048_576) return "1KB-1MB";
else if (size < 10_485_760) return "1MB-10MB";
else if (size < 104_857_600) return "10MB-100MB";
else return "大于100MB";
},
Collectors.averagingLong(FileInfo::getSize)
));
System.out.println("\nAverage size by size range:");
avgSizeByRange.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry ->
System.out.printf("%s: %,.2f bytes%n",
entry.getKey(), entry.getValue()));
}
}
朔风