未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用范围与待维护事项

本文适用于已有Java语法、面向对象和集合基础的本地教学练习;所用带字符集的FileReader/FileWriter构造方法要求Java 11及以上。正文未提供OpenCSV、Jackson依赖版本和构建配置,CSV/JSON独立运行前须创建data目录。XML、网络API和完整管道仅在导读中列出,未提供实现。示例折扣及用户数字为教学数据;金额使用double、年龄分组仅适用于18岁及以上样本,逐日活跃数之和不代表去重用户数,不能直接用于生产结算或业务报表。

Java数据处理与文件IO - 数据开发的核心技能

abstract 📋 Java数据处理与IO:数据开发的核心技能

🔍 为什么文件IO和数据处理很重要? 在数据开发工作中,我们需要从各种数据源读取数据、处理数据、然后输出到不同的目标系统。Java提供了丰富的IO类库和数据处理工具,掌握这些技能是数据开发者的必备基础。

🎯 本教程将帮助你掌握:

  • 📁 文件IO基础:字节流、字符流的原理和应用
  • 🔄 数据格式处理:JSON、CSV、XML等常见格式的读写
  • 🗂️ 大文件处理:高效处理大数据文件的技巧
  • 🌐 网络数据获取:从API和远程服务获取数据
  • 🔧 数据转换:不同格式间的数据转换和清洗
  • 📊 实战项目:完整的数据处理管道实现

⏱️ 学习时长:预计120分钟完成核心示例练习,实际用时取决于Java基础和环境配置

📁 Java IO基础原理

🌊 流的概念和分类

Java中的IO操作基于流(Stream)的概念:

/**
 * IO流的基础概念演示
 */
public class IOStreamBasics {
    public static void main(String[] args) {
        System.out.println("=== Java IO流分类 ===");
        
        /*
         * 按方向分类:
         * - 输入流(InputStream/Reader):从数据源读取数据
         * - 输出流(OutputStream/Writer):向目标写入数据
         * 
         * 按数据类型分类:
         * - 字节流(Byte Stream):处理二进制数据,以字节为单位
         * - 字符流(Character Stream):处理文本数据,以字符为单位
         * 
         * 按功能分类:
         * - 节点流:直接连接数据源/目标的流
         * - 处理流:对其他流进行包装,提供附加功能
         */
        
        demonstrateStreamTypes();
    }
    
    private static void demonstrateStreamTypes() {
        System.out.println("\n=== 流类型演示 ===");
        
        // 字节流示例
        System.out.println("字节流特点:");
        System.out.println("- 以byte为单位读写数据");
        System.out.println("- 适合处理二进制文件(图片、音频、压缩包等)");
        System.out.println("- 基类:InputStream/OutputStream");
        
        // 字符流示例
        System.out.println("\n字符流特点:");
        System.out.println("- 以char为单位读写数据");
        System.out.println("- 适合处理文本文件");
        System.out.println("- 基类:Reader/Writer");
        System.out.println("- 自动处理字符编码转换");
        
        // 缓冲流示例
        System.out.println("\n缓冲流特点:");
        System.out.println("- 内置缓冲区,减少系统调用次数");
        System.out.println("- 显著提高IO性能");
        System.out.println("- BufferedInputStream/BufferedReader");
    }
}

📝 文本文件读写

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import java.util.ArrayList;

/**
 * 文本文件读写操作详解
 */
public class TextFileOperations {
    
    public static void main(String[] args) {
        String filePath = "data/sample-data.txt";
        String outputPath = "data/processed-data.txt";
        
        // 确保目录存在
        createDirectoryIfNotExists("data");
        
        // 1. 传统IO方式
        System.out.println("=== 传统IO方式 ===");
        traditionalFileWrite(filePath);
        traditionalFileRead(filePath);
        
        // 2. NIO.2方式(推荐)
        System.out.println("\n=== NIO.2方式 ===");
        nioFileWrite(outputPath);
        nioFileRead(outputPath);
        
        // 3. 缓冲流方式(高性能)
        System.out.println("\n=== 缓冲流方式 ===");
        bufferedFileOperations("data/buffered-data.txt");
    }
    
    /**
     * 传统IO方式写文件
     */
    private static void traditionalFileWrite(String filePath) {
        System.out.println("使用传统IO写文件: " + filePath);
        
        try (FileWriter writer = new FileWriter(filePath, StandardCharsets.UTF_8)) {
            writer.write("# 数据处理示例文件\n");
            writer.write("timestamp,user_id,action,value\n");
            writer.write("2024-01-15 10:30:00,user001,login,1\n");
            writer.write("2024-01-15 10:31:15,user001,view_page,home\n");
            writer.write("2024-01-15 10:32:30,user002,login,1\n");
            writer.write("2024-01-15 10:33:45,user001,purchase,299.99\n");
            writer.write("2024-01-15 10:35:00,user002,view_page,product\n");
            
            System.out.println("文件写入完成");
        } catch (IOException e) {
            System.err.println("写文件出错: " + e.getMessage());
        }
    }
    
    /**
     * 传统IO方式读文件
     */
    private static void traditionalFileRead(String filePath) {
        System.out.println("使用传统IO读文件: " + filePath);
        
        try (FileReader reader = new FileReader(filePath, StandardCharsets.UTF_8);
             BufferedReader bufferedReader = new BufferedReader(reader)) {
            
            String line;
            int lineNumber = 0;
            
            while ((line = bufferedReader.readLine()) != null) {
                lineNumber++;
                System.out.println("第" + lineNumber + "行: " + line);
            }
            
            System.out.println("共读取 " + lineNumber + " 行数据");
            
        } catch (IOException e) {
            System.err.println("读文件出错: " + e.getMessage());
        }
    }
    
    /**
     * NIO.2方式文件操作(Java 7+推荐方式)
     */
    private static void nioFileWrite(String filePath) {
        System.out.println("使用NIO.2写文件: " + filePath);
        
        List<String> lines = new ArrayList<>();
        lines.add("# 使用NIO.2处理的数据文件");
        lines.add("product_id,product_name,category,price,stock");
        lines.add("P001,笔记本电脑,电子产品,8999.00,50");
        lines.add("P002,无线鼠标,电子产品,199.00,200");
        lines.add("P003,机械键盘,电子产品,599.00,100");
        lines.add("P004,显示器,电子产品,2999.00,30");
        lines.add("P005,充电宝,电子产品,299.00,150");
        
        try {
            Path path = Paths.get(filePath);
            Files.write(path, lines, StandardCharsets.UTF_8, 
                       StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
            
            System.out.println("NIO.2文件写入完成,共写入 " + lines.size() + " 行");
            
        } catch (IOException e) {
            System.err.println("NIO.2写文件出错: " + e.getMessage());
        }
    }
    
    /**
     * NIO.2方式读文件
     */
    private static void nioFileRead(String filePath) {
        System.out.println("使用NIO.2读文件: " + filePath);
        
        try {
            Path path = Paths.get(filePath);
            
            // 方式1: 读取所有行
            List<String> allLines = Files.readAllLines(path, StandardCharsets.UTF_8);
            System.out.println("读取到 " + allLines.size() + " 行数据:");
            
            for (int i = 0; i < allLines.size(); i++) {
                System.out.println("  " + (i + 1) + ": " + allLines.get(i));
            }
            
            // 方式2: 流式读取(适合大文件)
            System.out.println("\n流式读取示例:");
            try (java.util.stream.Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
                lines.filter(line -> !line.startsWith("#")) // 过滤注释行
                     .filter(line -> line.contains("电子产品")) // 过滤特定类别
                     .forEach(line -> System.out.println("  电子产品: " + line));
            }
                 
        } catch (IOException e) {
            System.err.println("NIO.2读文件出错: " + e.getMessage());
        }
    }
    
    /**
     * 缓冲流高性能文件操作
     */
    private static void bufferedFileOperations(String filePath) {
        System.out.println("使用缓冲流进行高性能文件操作: " + filePath);
        
        // 写入大量数据来演示性能
        long startTime = System.currentTimeMillis();
        
        try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8)) {
            
            writer.write("# 大数据量测试文件\n");
            writer.write("id,random_value,timestamp\n");
            
            // 生成10000条测试数据
            for (int i = 1; i <= 10000; i++) {
                String line = String.format("%d,%.2f,%d\n", 
                    i, Math.random() * 1000, System.currentTimeMillis());
                writer.write(line);
                
                // 每1000行打印一次进度
                if (i % 1000 == 0) {
                    System.out.println("  已写入 " + i + " 行数据");
                }
            }
            
        } catch (IOException e) {
            System.err.println("缓冲写入出错: " + e.getMessage());
        }
        
        long writeTime = System.currentTimeMillis() - startTime;
        System.out.println("写入完成,耗时: " + writeTime + " ms");
        
        // 读取和分析数据
        startTime = System.currentTimeMillis();
        
        try (BufferedReader reader = Files.newBufferedReader(Paths.get(filePath), StandardCharsets.UTF_8)) {
            
            String line;
            int totalLines = 0;
            double sum = 0.0;
            double max = Double.NEGATIVE_INFINITY;
            double min = Double.MAX_VALUE;
            
            // 跳过标题行
            reader.readLine(); // #注释行
            reader.readLine(); // 标题行
            
            while ((line = reader.readLine()) != null) {
                String[] parts = line.split(",");
                if (parts.length >= 2) {
                    try {
                        double value = Double.parseDouble(parts[1]);
                        sum += value;
                        max = Math.max(max, value);
                        min = Math.min(min, value);
                        totalLines++;
                    } catch (NumberFormatException e) {
                        System.err.println("数据格式错误: " + line);
                    }
                }
            }
            
            if (totalLines > 0) {
                double average = sum / totalLines;
                System.out.println("数据分析结果:");
                System.out.println("  总行数: " + totalLines);
                System.out.println("  数值总和: " + String.format("%.2f", sum));
                System.out.println("  平均值: " + String.format("%.2f", average));
                System.out.println("  最大值: " + String.format("%.2f", max));
                System.out.println("  最小值: " + String.format("%.2f", min));
            }
            
        } catch (IOException e) {
            System.err.println("缓冲读取出错: " + e.getMessage());
        }
        
        long readTime = System.currentTimeMillis() - startTime;
        System.out.println("读取分析完成,耗时: " + readTime + " ms");
    }
    
    /**
     * 创建目录(如果不存在)
     */
    private static void createDirectoryIfNotExists(String dirPath) {
        try {
            Path path = Paths.get(dirPath);
            if (!Files.exists(path)) {
                Files.createDirectories(path);
                System.out.println("创建目录: " + dirPath);
            }
        } catch (IOException e) {
            System.err.println("创建目录失败: " + e.getMessage());
        }
    }
}

📊 常见数据格式处理

🎯 CSV文件处理

CSV是数据处理中最常见的格式之一:

import com.opencsv.*;
import com.opencsv.exceptions.CsvException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * CSV文件处理专业工具类
 */
public class CSVProcessor {
    
    public static void main(String[] args) {
        String csvFile = "data/sales-data.csv";
        String outputFile = "data/processed-sales.csv";
        
        // 创建示例数据
        createSampleCSV(csvFile);
        
        // 读取和处理CSV
        List<SalesRecord> records = readCSVRecords(csvFile);
        
        // 数据分析
        analyzeData(records);
        
        // 处理数据并输出
        List<SalesRecord> processedRecords = processData(records);
        writeCSVRecords(outputFile, processedRecords);
    }
    
    /**
     * 销售记录数据模型
     */
    public static class SalesRecord {
        private String orderId;
        private String productName;
        private String category;
        private double unitPrice;
        private int quantity;
        private String customerType;
        private String orderDate;
        private double totalAmount;
        
        // 构造方法
        public SalesRecord(String orderId, String productName, String category, 
                          double unitPrice, int quantity, String customerType, String orderDate) {
            this.orderId = orderId;
            this.productName = productName;
            this.category = category;
            this.unitPrice = unitPrice;
            this.quantity = quantity;
            this.customerType = customerType;
            this.orderDate = orderDate;
            this.totalAmount = unitPrice * quantity;
        }
        
        // Getter和Setter方法
        public String getOrderId() { return orderId; }
        public String getProductName() { return productName; }
        public String getCategory() { return category; }
        public double getUnitPrice() { return unitPrice; }
        public int getQuantity() { return quantity; }
        public String getCustomerType() { return customerType; }
        public String getOrderDate() { return orderDate; }
        public double getTotalAmount() { return totalAmount; }
        
        public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; }
        
        @Override
        public String toString() {
            return String.format("SalesRecord{orderId='%s', product='%s', category='%s', " +
                    "unitPrice=%.2f, quantity=%d, total=%.2f, customer='%s', date='%s'}",
                    orderId, productName, category, unitPrice, quantity, totalAmount, customerType, orderDate);
        }
    }
    
    /**
     * 创建示例CSV文件
     */
    private static void createSampleCSV(String filePath) {
        System.out.println("创建示例CSV文件: " + filePath);
        
        String[] headers = {"订单ID", "商品名称", "类别", "单价", "数量", "客户类型", "订单日期"};
        String[][] data = {
            {"ORD001", "笔记本电脑", "电子产品", "8999.00", "2", "企业客户", "2024-01-15"},
            {"ORD002", "无线鼠标", "电子产品", "199.00", "5", "个人客户", "2024-01-15"},
            {"ORD003", "办公椅", "办公用品", "1299.00", "3", "企业客户", "2024-01-16"},
            {"ORD004", "显示器", "电子产品", "2999.00", "1", "个人客户", "2024-01-16"},
            {"ORD005", "键盘", "电子产品", "599.00", "4", "个人客户", "2024-01-17"},
            {"ORD006", "打印纸", "办公用品", "29.90", "20", "企业客户", "2024-01-17"},
            {"ORD007", "充电宝", "电子产品", "299.00", "8", "个人客户", "2024-01-18"},
            {"ORD008", "文件夹", "办公用品", "15.50", "50", "企业客户", "2024-01-18"}
        };
        
        try (Writer output = new FileWriter(filePath, StandardCharsets.UTF_8);
             CSVWriter writer = new CSVWriter(output)) {
            // 写入UTF-8 BOM,帮助Excel识别中文编码
            output.write("\uFEFF");
            
            // 写入标题行
            writer.writeNext(headers);
            
            // 写入数据行
            for (String[] row : data) {
                writer.writeNext(row);
            }
            
            System.out.println("CSV文件创建完成,共写入 " + (data.length + 1) + " 行");
            
        } catch (IOException e) {
            System.err.println("创建CSV文件失败: " + e.getMessage());
        }
    }
    
    /**
     * 读取CSV文件并转换为对象列表
     */
    private static List<SalesRecord> readCSVRecords(String filePath) {
        System.out.println("读取CSV文件: " + filePath);
        List<SalesRecord> records = new ArrayList<>();
        
        try (CSVReader reader = new CSVReader(new FileReader(filePath, StandardCharsets.UTF_8))) {
            
            // 跳过标题行
            String[] headers = reader.readNext();
            System.out.println("CSV标题: " + String.join(", ", headers));
            
            String[] line;
            int lineNumber = 1;
            
            while ((line = reader.readNext()) != null) {
                lineNumber++;
                
                try {
                    if (line.length >= 7) {
                        SalesRecord record = new SalesRecord(
                            line[0].trim(),                           // 订单ID
                            line[1].trim(),                           // 商品名称
                            line[2].trim(),                           // 类别
                            Double.parseDouble(line[3].trim()),       // 单价
                            Integer.parseInt(line[4].trim()),         // 数量
                            line[5].trim(),                           // 客户类型
                            line[6].trim()                            // 订单日期
                        );
                        
                        records.add(record);
                        
                    } else {
                        System.err.println("第 " + lineNumber + " 行数据格式不正确: " + String.join(",", line));
                    }
                    
                } catch (NumberFormatException e) {
                    System.err.println("第 " + lineNumber + " 行数据类型转换错误: " + e.getMessage());
                }
            }
            
        } catch (IOException | CsvException e) {
            System.err.println("读取CSV文件失败: " + e.getMessage());
        }
        
        System.out.println("成功读取 " + records.size() + " 条销售记录");
        return records;
    }
    
    /**
     * 数据分析
     */
    private static void analyzeData(List<SalesRecord> records) {
        System.out.println("\n=== 销售数据分析 ===");
        
        if (records.isEmpty()) {
            System.out.println("没有数据可分析");
            return;
        }
        
        // 基础统计
        double totalRevenue = records.stream().mapToDouble(SalesRecord::getTotalAmount).sum();
        int totalQuantity = records.stream().mapToInt(SalesRecord::getQuantity).sum();
        double avgOrderValue = totalRevenue / records.size();
        
        System.out.println("基础统计:");
        System.out.println("  总订单数: " + records.size());
        System.out.println("  总销售额: " + String.format("%.2f", totalRevenue));
        System.out.println("  总销售量: " + totalQuantity);
        System.out.println("  平均订单价值: " + String.format("%.2f", avgOrderValue));
        
        // 按类别分析
        Map<String, Double> categoryRevenue = new HashMap<>();
        Map<String, Integer> categoryCount = new HashMap<>();
        
        for (SalesRecord record : records) {
            String category = record.getCategory();
            categoryRevenue.merge(category, record.getTotalAmount(), Double::sum);
            categoryCount.merge(category, 1, Integer::sum);
        }
        
        System.out.println("\n按类别分析:");
        for (String category : categoryRevenue.keySet()) {
            double revenue = categoryRevenue.get(category);
            int count = categoryCount.get(category);
            double percentage = (revenue / totalRevenue) * 100;
            
            System.out.println("  " + category + ":");
            System.out.println("    订单数: " + count);
            System.out.println("    销售额: " + String.format("%.2f", revenue));
            System.out.println("    占比: " + String.format("%.1f%%", percentage));
        }
        
        // 按客户类型分析
        Map<String, Double> customerTypeRevenue = new HashMap<>();
        for (SalesRecord record : records) {
            customerTypeRevenue.merge(record.getCustomerType(), record.getTotalAmount(), Double::sum);
        }
        
        System.out.println("\n按客户类型分析:");
        for (String customerType : customerTypeRevenue.keySet()) {
            double revenue = customerTypeRevenue.get(customerType);
            double percentage = (revenue / totalRevenue) * 100;
            System.out.println("  " + customerType + ": " + 
                String.format("%.2f", revenue) + " (" + String.format("%.1f%%", percentage) + ")");
        }
        
        // 找出最大订单
        SalesRecord maxOrder = records.stream()
            .max(Comparator.comparing(SalesRecord::getTotalAmount))
            .orElse(null);
        
        if (maxOrder != null) {
            System.out.println("\n最大订单:");
            System.out.println("  " + maxOrder);
        }
    }
    
    /**
     * 数据处理:添加折扣计算
     */
    private static List<SalesRecord> processData(List<SalesRecord> records) {
        System.out.println("\n=== 数据处理:计算折扣 ===");
        
        List<SalesRecord> processedRecords = new ArrayList<>();
        
        for (SalesRecord record : records) {
            // 复制记录
            SalesRecord processedRecord = new SalesRecord(
                record.getOrderId(),
                record.getProductName(),
                record.getCategory(),
                record.getUnitPrice(),
                record.getQuantity(),
                record.getCustomerType(),
                record.getOrderDate()
            );
            
            // 应用业务规则计算折扣
            double originalAmount = record.getTotalAmount();
            double discount = calculateDiscount(record);
            double finalAmount = originalAmount * (1 - discount);
            
            processedRecord.setTotalAmount(finalAmount);
            processedRecords.add(processedRecord);
            
            if (discount > 0) {
                System.out.println("订单 " + record.getOrderId() + 
                    " 应用 " + String.format("%.1f%%", discount * 100) + 
                    " 折扣,金额从 " + String.format("%.2f", originalAmount) + 
                    " 调整为 " + String.format("%.2f", finalAmount));
            }
        }
        
        return processedRecords;
    }
    
    /**
     * 计算折扣的业务逻辑
     */
    private static double calculateDiscount(SalesRecord record) {
        double discount = 0.0;
        
        // 企业客户享受5%折扣
        if ("企业客户".equals(record.getCustomerType())) {
            discount += 0.05;
        }
        
        // 大单折扣:订单金额超过10000享受额外3%折扣
        if (record.getTotalAmount() > 10000) {
            discount += 0.03;
        }
        
        // 批量购买折扣:数量超过10件享受2%折扣
        if (record.getQuantity() > 10) {
            discount += 0.02;
        }
        
        // 最大折扣限制10%
        return Math.min(discount, 0.10);
    }
    
    /**
     * 写入处理后的CSV文件
     */
    private static void writeCSVRecords(String filePath, List<SalesRecord> records) {
        System.out.println("\n写入处理后的CSV文件: " + filePath);
        
        try (CSVWriter writer = new CSVWriter(new FileWriter(filePath, StandardCharsets.UTF_8))) {
            
            // 写入标题行
            String[] headers = {"订单ID", "商品名称", "类别", "单价", "数量", "客户类型", "订单日期", "最终金额"};
            writer.writeNext(headers);
            
            // 写入数据行
            for (SalesRecord record : records) {
                String[] row = {
                    record.getOrderId(),
                    record.getProductName(),
                    record.getCategory(),
                    String.valueOf(record.getUnitPrice()),
                    String.valueOf(record.getQuantity()),
                    record.getCustomerType(),
                    record.getOrderDate(),
                    String.format("%.2f", record.getTotalAmount())
                };
                writer.writeNext(row);
            }
            
            System.out.println("CSV文件写入完成,共 " + records.size() + " 条记录");
            
        } catch (IOException e) {
            System.err.println("写入CSV文件失败: " + e.getMessage());
        }
    }
}

🎯 JSON数据处理

JSON是现代数据交换的主要格式:

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
import com.fasterxml.jackson.core.type.TypeReference;
import java.io.*;
import java.util.*;

/**
 * JSON数据处理工具类
 */
public class JSONProcessor {
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    public static void main(String[] args) {
        // 1. 创建示例JSON数据
        createSampleJSON();
        
        // 2. 读取和解析JSON
        parseJSONData();
        
        // 3. JSON数据转换
        transformJSONData();
        
        // 4. 处理复杂嵌套JSON
        processNestedJSON();
    }
    
    /**
     * 用户数据模型
     */
    public static class User {
        private String userId;
        private String username;
        private String email;
        private int age;
        private List<String> interests;
        private Map<String, Object> metadata;
        
        // 构造方法
        public User() {}
        
        public User(String userId, String username, String email, int age) {
            this.userId = userId;
            this.username = username;
            this.email = email;
            this.age = age;
            this.interests = new ArrayList<>();
            this.metadata = new HashMap<>();
        }
        
        // Getter和Setter方法
        public String getUserId() { return userId; }
        public void setUserId(String userId) { this.userId = userId; }
        
        public String getUsername() { return username; }
        public void setUsername(String username) { this.username = username; }
        
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        
        public int getAge() { return age; }
        public void setAge(int age) { this.age = age; }
        
        public List<String> getInterests() { return interests; }
        public void setInterests(List<String> interests) { this.interests = interests; }
        
        public Map<String, Object> getMetadata() { return metadata; }
        public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; }
        
        @Override
        public String toString() {
            return String.format("User{userId='%s', username='%s', email='%s', age=%d, interests=%s}",
                    userId, username, email, age, interests);
        }
    }
    
    /**
     * 创建示例JSON数据文件
     */
    private static void createSampleJSON() {
        System.out.println("=== 创建示例JSON数据 ===");
        
        try {
            // 创建用户数据
            List<User> users = new ArrayList<>();
            
            User user1 = new User("U001", "张三", "zhangsan@example.com", 28);
            user1.getInterests().addAll(Arrays.asList("编程", "数据分析", "机器学习"));
            user1.getMetadata().put("registerDate", "2023-01-15");
            user1.getMetadata().put("loginCount", 125);
            user1.getMetadata().put("vipLevel", "Gold");
            
            User user2 = new User("U002", "李四", "lisi@example.com", 32);
            user2.getInterests().addAll(Arrays.asList("大数据", "云计算", "人工智能"));
            user2.getMetadata().put("registerDate", "2023-02-20");
            user2.getMetadata().put("loginCount", 89);
            user2.getMetadata().put("vipLevel", "Silver");
            
            User user3 = new User("U003", "王五", "wangwu@example.com", 25);
            user3.getInterests().addAll(Arrays.asList("前端开发", "用户体验", "产品设计"));
            user3.getMetadata().put("registerDate", "2023-03-10");
            user3.getMetadata().put("loginCount", 256);
            user3.getMetadata().put("vipLevel", "Platinum");
            
            users.add(user1);
            users.add(user2);
            users.add(user3);
            
            // 写入JSON文件
            objectMapper.writerWithDefaultPrettyPrinter()
                       .writeValue(new File("data/users.json"), users);
            
            System.out.println("用户JSON文件创建完成");
            
            // 创建复杂的嵌套JSON
            createComplexJSON();
            
        } catch (IOException e) {
            System.err.println("创建JSON文件失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建复杂的嵌套JSON结构
     */
    private static void createComplexJSON() throws IOException {
        // 使用JsonNode构建复杂结构
        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("reportId", "RPT-2024-001");
        rootNode.put("generatedAt", System.currentTimeMillis());
        rootNode.put("reportType", "用户行为分析");
        
        // 添加数据汇总
        ObjectNode summaryNode = objectMapper.createObjectNode();
        summaryNode.put("totalUsers", 1250);
        summaryNode.put("activeUsers", 892);
        summaryNode.put("newUsers", 156);
        summaryNode.put("avgSessionTime", 18.5);
        rootNode.set("summary", summaryNode);
        
        // 添加分类数据
        ArrayNode categoriesNode = objectMapper.createArrayNode();
        
        ObjectNode category1 = objectMapper.createObjectNode();
        category1.put("name", "移动端用户");
        category1.put("count", 750);
        category1.put("percentage", 60.0);
        
        ArrayNode topPages1 = objectMapper.createArrayNode();
        topPages1.add("首页");
        topPages1.add("产品列表");
        topPages1.add("个人中心");
        category1.set("topPages", topPages1);
        
        ObjectNode category2 = objectMapper.createObjectNode();
        category2.put("name", "桌面端用户");
        category2.put("count", 500);
        category2.put("percentage", 40.0);
        
        ArrayNode topPages2 = objectMapper.createArrayNode();
        topPages2.add("数据分析");
        topPages2.add("报表查看");
        topPages2.add("系统设置");
        category2.set("topPages", topPages2);
        
        categoriesNode.add(category1);
        categoriesNode.add(category2);
        rootNode.set("categories", categoriesNode);
        
        // 添加时间序列数据
        ArrayNode timeSeriesNode = objectMapper.createArrayNode();
        String[] dates = {"2024-01-01", "2024-01-02", "2024-01-03", "2024-01-04", "2024-01-05"};
        int[] values = {120, 135, 98, 156, 142};
        
        for (int i = 0; i < dates.length; i++) {
            ObjectNode dataPoint = objectMapper.createObjectNode();
            dataPoint.put("date", dates[i]);
            dataPoint.put("activeUsers", values[i]);
            dataPoint.put("growth", i > 0 ? ((double)(values[i] - values[i-1]) / values[i-1] * 100) : 0.0);
            timeSeriesNode.add(dataPoint);
        }
        rootNode.set("timeSeries", timeSeriesNode);
        
        // 写入文件
        objectMapper.writerWithDefaultPrettyPrinter()
                   .writeValue(new File("data/complex-report.json"), rootNode);
        
        System.out.println("复杂JSON报表文件创建完成");
    }
    
    /**
     * 解析JSON数据
     */
    private static void parseJSONData() {
        System.out.println("\n=== 解析JSON数据 ===");
        
        try {
            // 方式1: 解析为对象列表
            System.out.println("方式1: 解析为Java对象");
            List<User> users = objectMapper.readValue(
                new File("data/users.json"), 
                new TypeReference<List<User>>() {}
            );
            
            System.out.println("读取到 " + users.size() + " 个用户:");
            for (User user : users) {
                System.out.println("  " + user);
                System.out.println("    兴趣: " + user.getInterests());
                System.out.println("    元数据: " + user.getMetadata());
            }
            
            // 方式2: 解析为JsonNode(更灵活)
            System.out.println("\n方式2: 解析为JsonNode");
            JsonNode rootNode = objectMapper.readTree(new File("data/users.json"));
            
            if (rootNode.isArray()) {
                System.out.println("JSON数组,包含 " + rootNode.size() + " 个元素");
                
                for (int i = 0; i < rootNode.size(); i++) {
                    JsonNode userNode = rootNode.get(i);
                    String userId = userNode.get("userId").asText();
                    String username = userNode.get("username").asText();
                    int age = userNode.get("age").asInt();
                    
                    System.out.println("  用户 " + (i + 1) + ": " + username + " (ID: " + userId + ", 年龄: " + age + ")");
                    
                    // 处理数组类型的字段
                    JsonNode interestsNode = userNode.get("interests");
                    if (interestsNode.isArray()) {
                        List<String> interests = new ArrayList<>();
                        for (JsonNode interestNode : interestsNode) {
                            interests.add(interestNode.asText());
                        }
                        System.out.println("    兴趣: " + interests);
                    }
                }
            }
            
        } catch (IOException e) {
            System.err.println("解析JSON数据失败: " + e.getMessage());
        }
    }
    
    /**
     * JSON数据转换
     */
    private static void transformJSONData() {
        System.out.println("\n=== JSON数据转换 ===");
        
        try {
            // 读取原始数据
            List<User> users = objectMapper.readValue(
                new File("data/users.json"), 
                new TypeReference<List<User>>() {}
            );
            
            // 数据转换:创建用户统计报告
            Map<String, Object> report = new HashMap<>();
            report.put("reportTitle", "用户数据分析报告");
            report.put("generatedAt", new Date().toString());
            report.put("totalUsers", users.size());
            
            // 年龄分布统计
            Map<String, Integer> ageGroups = new HashMap<>();
            ageGroups.put("18-25", 0);
            ageGroups.put("26-35", 0);
            ageGroups.put("36-45", 0);
            ageGroups.put("46+", 0);
            
            for (User user : users) {
                int age = user.getAge();
                if (age <= 25) {
                    ageGroups.merge("18-25", 1, Integer::sum);
                } else if (age <= 35) {
                    ageGroups.merge("26-35", 1, Integer::sum);
                } else if (age <= 45) {
                    ageGroups.merge("36-45", 1, Integer::sum);
                } else {
                    ageGroups.merge("46+", 1, Integer::sum);
                }
            }
            report.put("ageDistribution", ageGroups);
            
            // 兴趣统计
            Map<String, Integer> interestCount = new HashMap<>();
            for (User user : users) {
                for (String interest : user.getInterests()) {
                    interestCount.merge(interest, 1, Integer::sum);
                }
            }
            report.put("popularInterests", interestCount);
            
            // VIP等级统计
            Map<String, Integer> vipLevels = new HashMap<>();
            for (User user : users) {
                Object vipLevel = user.getMetadata().get("vipLevel");
                if (vipLevel != null) {
                    vipLevels.merge(vipLevel.toString(), 1, Integer::sum);
                }
            }
            report.put("vipDistribution", vipLevels);
            
            // 平均登录次数
            double avgLoginCount = users.stream()
                .mapToInt(u -> (Integer) u.getMetadata().getOrDefault("loginCount", 0))
                .average()
                .orElse(0.0);
            report.put("averageLoginCount", Math.round(avgLoginCount * 100.0) / 100.0);
            
            // 写入转换后的报告
            objectMapper.writerWithDefaultPrettyPrinter()
                       .writeValue(new File("data/user-report.json"), report);
            
            System.out.println("用户分析报告已生成: data/user-report.json");
            System.out.println("报告内容:");
            System.out.println("  总用户数: " + report.get("totalUsers"));
            System.out.println("  年龄分布: " + report.get("ageDistribution"));
            System.out.println("  热门兴趣: " + report.get("popularInterests"));
            System.out.println("  VIP分布: " + report.get("vipDistribution"));
            System.out.println("  平均登录次数: " + report.get("averageLoginCount"));
            
        } catch (IOException e) {
            System.err.println("JSON数据转换失败: " + e.getMessage());
        }
    }
    
    /**
     * 处理复杂嵌套JSON
     */
    private static void processNestedJSON() {
        System.out.println("\n=== 处理复杂嵌套JSON ===");
        
        try {
            JsonNode reportNode = objectMapper.readTree(new File("data/complex-report.json"));
            
            System.out.println("报告ID: " + reportNode.get("reportId").asText());
            System.out.println("报告类型: " + reportNode.get("reportType").asText());
            
            // 处理汇总数据
            JsonNode summaryNode = reportNode.get("summary");
            if (summaryNode != null) {
                System.out.println("\n数据汇总:");
                System.out.println("  总用户数: " + summaryNode.get("totalUsers").asInt());
                System.out.println("  活跃用户数: " + summaryNode.get("activeUsers").asInt());
                System.out.println("  新用户数: " + summaryNode.get("newUsers").asInt());
                System.out.println("  平均会话时长: " + summaryNode.get("avgSessionTime").asDouble() + " 分钟");
            }
            
            // 处理分类数据
            JsonNode categoriesNode = reportNode.get("categories");
            if (categoriesNode != null && categoriesNode.isArray()) {
                System.out.println("\n用户分类:");
                for (JsonNode categoryNode : categoriesNode) {
                    String name = categoryNode.get("name").asText();
                    int count = categoryNode.get("count").asInt();
                    double percentage = categoryNode.get("percentage").asDouble();
                    
                    System.out.println("  " + name + ": " + count + " 用户 (" + percentage + "%)");
                    
                    JsonNode topPagesNode = categoryNode.get("topPages");
                    if (topPagesNode != null && topPagesNode.isArray()) {
                        System.out.print("    热门页面: ");
                        List<String> pages = new ArrayList<>();
                        for (JsonNode pageNode : topPagesNode) {
                            pages.add(pageNode.asText());
                        }
                        System.out.println(String.join(", ", pages));
                    }
                }
            }
            
            // 处理时间序列数据
            JsonNode timeSeriesNode = reportNode.get("timeSeries");
            if (timeSeriesNode != null && timeSeriesNode.isArray()) {
                System.out.println("\n时间序列数据:");
                for (JsonNode dataPoint : timeSeriesNode) {
                    String date = dataPoint.get("date").asText();
                    int activeUsers = dataPoint.get("activeUsers").asInt();
                    double growth = dataPoint.get("growth").asDouble();
                    
                    System.out.println("  " + date + ": " + activeUsers + " 活跃用户 (增长: " + 
                        String.format("%.1f%%", growth) + ")");
                }
            }
            
            // 数据处理:计算样本期间累计活跃人次和相邻日期平均增长率
            processTimeSeriesData(timeSeriesNode);
            
        } catch (IOException e) {
            System.err.println("处理复杂JSON失败: " + e.getMessage());
        }
    }
    
    /**
     * 处理时间序列数据并计算统计指标
     */
    private static void processTimeSeriesData(JsonNode timeSeriesNode) {
        if (timeSeriesNode == null || !timeSeriesNode.isArray()) {
            return;
        }
        
        System.out.println("\n时间序列数据分析:");
        
        int totalActiveUsers = 0;
        double totalGrowth = 0.0;
        int dataPoints = 0;
        int maxUsers = 0;
        int minUsers = Integer.MAX_VALUE;
        String maxDate = "";
        String minDate = "";
        
        for (JsonNode dataPoint : timeSeriesNode) {
            int activeUsers = dataPoint.get("activeUsers").asInt();
            double growth = dataPoint.get("growth").asDouble();
            String date = dataPoint.get("date").asText();
            
            totalActiveUsers += activeUsers;
            // 首日growth为占位值,不纳入相邻日期增长率的平均值
            if (dataPoints > 0) {
                totalGrowth += growth;
            }
            dataPoints++;
            
            if (activeUsers > maxUsers) {
                maxUsers = activeUsers;
                maxDate = date;
            }
            
            if (activeUsers < minUsers) {
                minUsers = activeUsers;
                minDate = date;
            }
        }
        
        if (dataPoints > 0) {
            double avgActiveUsers = (double) totalActiveUsers / dataPoints;
            double avgGrowth = dataPoints > 1 ? totalGrowth / (dataPoints - 1) : 0.0;
            
            System.out.println("  数据点数量: " + dataPoints);
            System.out.println("  样本期间累计活跃人次(未跨日去重): " + totalActiveUsers);
            System.out.println("  平均活跃用户数: " + String.format("%.1f", avgActiveUsers));
            System.out.println("  相邻日期平均增长率: " + (dataPoints > 1 ? String.format("%.2f%%", avgGrowth) : "无可比较日期,导出值以0占位"));
            System.out.println("  最高活跃用户数: " + maxUsers + " (" + maxDate + ")");
            System.out.println("  最低活跃用户数: " + minUsers + " (" + minDate + ")");
            
            // 创建处理后的数据摘要
            Map<String, Object> analysisSummary = new HashMap<>();
            analysisSummary.put("totalDataPoints", dataPoints);
            // 保留原导出字段名;此值为逐日活跃数之和,并非期间去重用户数
            analysisSummary.put("totalActiveUsers", totalActiveUsers);
            analysisSummary.put("averageActiveUsers", Math.round(avgActiveUsers * 100.0) / 100.0);
            analysisSummary.put("averageGrowthRate", Math.round(avgGrowth * 100.0) / 100.0);
            analysisSummary.put("maxActiveUsers", maxUsers);
            analysisSummary.put("maxActiveUsersDate", maxDate);
            analysisSummary.put("minActiveUsers", minUsers);
            analysisSummary.put("minActiveUsersDate", minDate);
            
            try {
                objectMapper.writerWithDefaultPrettyPrinter()
                           .writeValue(new File("data/timeseries-analysis.json"), analysisSummary);
                System.out.println("  时间序列分析结果已保存: data/timeseries-analysis.json");
            } catch (IOException e) {
                System.err.println("保存分析结果失败: " + e.getMessage());
            }
        }
    }
}

相关学习资源

继续学习

高级主题