Hutool Hutool
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
  • 最佳实践
  • 数据抽取
  • 数据清洗
    • 📚 概述
    • 🚀 快速开始
      • 1. 添加依赖
      • 2. 配置数据库
    • 📖 核心功能
      • 一、数据抽取
      • 1. 从网页获取数据
      • 2. 从文件获取数据
      • 3. 从 JSON API 获取数据
      • 二、数据转换
      • 1. 日期转换
      • 2. 数字转换
      • 3. 字符串转换
      • 4. JSON 转换
      • 三、数据清洗
      • 1. 数据去重
      • 2. 缺失值处理
      • 3. 格式标准化
      • 4. 数据验证
      • 5. 数据过滤
      • 四、数据入库
      • 1. 单条数据入库
      • 2. 批量数据入库
      • 3. 使用事务入库
      • 4. 数据更新
    • 💡 完整示例
      • 示例1:网页数据清洗与入库
      • 示例2:CSV数据清洗与入库
      • 示例3:JSON数据清洗与入库
    • 🎨 高级技巧
      • 1. 使用多线程提高效率
      • 2. 分批处理大数据量
      • 3. 使用缓存减少重复请求
      • 4. 数据质量监控
      • 5. 使用事务保证数据一致性
    • ⚠️ 注意事项
      • 1. 数据备份
      • 2. 错误处理
      • 3. 性能优化
      • 4. 数据隐私保护
      • 5. 测试验证
    • 📊 最佳实践
      • 1. 建立数据清洗规则
      • 2. 采用ETL流程
      • 3. 日志记录
      • 4. 监控和反馈
      • 5. 文档化
    • 🎯 总结
  • 最佳实践
Hutool
2026-01-03
目录

数据清洗

# 📚 概述

数据清洗是数据处理流程中的关键环节,用于从原始数据中识别和纠正错误、不一致性,以及处理缺失值,最终得到高质量、可用的数据。Hutool 提供了丰富的工具类来简化数据清洗过程,主要包括:

  • 数据抽取:使用 HttpUtil、ReUtil 等工具从各种数据源获取数据
  • 数据转换:使用 DateUtil、NumberUtil、StrUtil 等工具转换数据格式
  • 数据清洗:使用 CollUtil、StrUtil、Validator 等工具处理数据质量问题
  • 数据入库:使用 Db 模块将清洗后的数据保存到数据库

通过这些工具的组合使用,可以高效地完成从数据采集到最终入库的完整数据清洗流程。

# 🚀 快速开始

# 1. 添加依赖

<!-- 如果使用MySQL数据库,需要添加MySQL驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

# 2. 配置数据库

在 src/main/resources 目录下创建 db.setting 文件:

url = jdbc:mysql://localhost:3306/data_cleaning
user = root
pass = 123456

## 可选配置
showSql = true
formatSql = false
showParams = true
sqlLevel = debug

# 📖 核心功能

# 一、数据抽取

数据抽取是数据清洗的第一步,用于从各种数据源获取原始数据。

# 1. 从网页获取数据

// 使用 HttpUtil 获取网页内容
String url = "https://www.example.com/data";
String html = HttpUtil.get(url);

// 使用 ReUtil 提取数据
String title = ReUtil.get("<title>(.*?)</title>", html, 1);
List<String> links = ReUtil.findAll("<a href=\"(.*?)\"", html, 1);

# 2. 从文件获取数据

// 从文本文件读取数据
List<String> lines = FileUtil.readLines("data.txt", CharsetUtil.UTF_8);

// 从 CSV 文件读取数据
CsvReader reader = CsvUtil.getReader();
List<CsvRow> rows = reader.read(FileUtil.file("data.csv"));

# 3. 从 JSON API 获取数据

// 从 API 获取 JSON 数据
String apiUrl = "https://api.example.com/data";
String jsonStr = HttpUtil.get(apiUrl);

// 解析 JSON 数据
JSONObject json = JSONUtil.parseObj(jsonStr);
JSONArray dataArray = json.getJSONArray("data");

# 二、数据转换

数据转换是将原始数据转换为标准化格式的过程,包括日期转换、数字转换、字符串转换等。

# 1. 日期转换

// 自动识别日期格式并转换
String dateStr = "2023-01-01";
Date date = DateUtil.parse(dateStr);

// 自定义日期格式转换
String customDateStr = "2023/01/01 12:00:00";
Date customDate = DateUtil.parse(customDateStr, "yyyy/MM/dd HH:mm:ss");

// 日期格式化
String formattedDate = DateUtil.format(date, "yyyy-MM-dd");
String formattedDateTime = DateUtil.formatDateTime(date);

// 相对时间转换
Date yesterday = DateUtil.yesterday();
Date lastWeek = DateUtil.offsetWeek(new Date(), -1);
Date nextMonth = DateUtil.offsetMonth(new Date(), 1);

// 时间戳转换
long timestamp = System.currentTimeMillis();
Date dateFromTimestamp = DateUtil.date(timestamp);

# 2. 数字转换

// 字符串转数字
String numStr = "123.45";
double num = NumberUtil.parseDouble(numStr);
int intNum = NumberUtil.parseInt("123");

// 数字格式化
String formattedNum = NumberUtil.formatNum(1234567.89, 2); // 1,234,567.89
String formattedPercent = NumberUtil.formatPercent(0.756, 1); // 75.6%

// 数字四舍五入
BigDecimal rounded = NumberUtil.round(123.456, 2); // 123.46

// 数值比较
boolean isGreater = NumberUtil.isGreater(100, 99); // true
boolean isBetween = NumberUtil.isBetween(50, 0, 100); // true

# 3. 字符串转换

// 大小写转换
String upper = StrUtil.upperFirst("hello"); // Hello
String lower = StrUtil.lowerFirst("HELLO"); // hELLO

// 去除空白字符
String cleanStr = StrUtil.cleanBlank("  hello   world  "); // helloworld

// 去除前后空白
String trimmed = StrUtil.trim("  hello  "); // hello

// 替换字符串
String replaced = StrUtil.replace("hello world", "world", "Hutool"); // hello Hutool

// 分割字符串
String[] parts = StrUtil.split("a,b,c", ","); // ["a", "b", "c"]

// 字符串转数组
int[] intArray = Convert.toIntArray("1,2,3,4,5"); // [1, 2, 3, 4, 5]

# 4. JSON 转换

// JSON 字符串转对象
String jsonStr = "{\"name\":\"张三\",\"age\":25}";
JSONObject jsonObj = JSONUtil.parseObj(jsonStr);

// JSON 转 JavaBean
User user = JSONUtil.toBean(jsonStr, User.class);

// JavaBean 转 JSON
String userJson = JSONUtil.toJsonStr(user);

// JSONArray 转 List
JSONArray jsonArray = JSONUtil.parseArray("[1,2,3,4,5]");
List<Integer> list = JSONUtil.toList(jsonArray, Integer.class);

# 三、数据清洗

数据清洗是处理数据质量问题的过程,包括去重、缺失值处理、格式标准化等。

# 1. 数据去重

// 集合去重
List<String> list = CollUtil.newArrayList("a", "b", "a", "c", "b");
List<String> distinctList = CollUtil.distinct(list); // ["a", "b", "c"]

// 根据属性去重
List<User> users = CollUtil.newArrayList(
    new User("张三", 25),
    new User("李四", 30),
    new User("张三", 25)
);
List<User> distinctUsers = CollUtil.distinctByProperty(users, "name");

// 数据库去重
// 查询已存在的数据
List<Entity> existingData = Db.use().findAll("user");
Set<String> existingNames = existingData.stream()
    .map(e -> e.getStr("name"))
    .collect(Collectors.toSet());

// 过滤重复数据
List<User> newUsers = users.stream()
    .filter(user -> !existingNames.contains(user.getName()))
    .collect(Collectors.toList());

# 2. 缺失值处理

// 替换空值
String str = StrUtil.emptyToDefault(null, "默认值"); // 默认值
Object value = ObjectUtil.defaultIfNull(null, "默认值"); // 默认值

// 过滤空值
List<String> listWithNull = CollUtil.newArrayList("a", null, "b", "", "c");
List<String> listWithoutNull = CollUtil.removeEmpty(listWithNull); // ["a", "b", "c"]

// 缺失值填充
for (User user : users) {
    if (StrUtil.isBlank(user.getName())) {
        user.setName("未知");
    }
    if (user.getAge() == null) {
        user.setAge(0);
    }
}

# 3. 格式标准化

// 标准化日期格式
List<String> dateStrs = CollUtil.newArrayList("2023-01-01", "2023/01/02", "2023.01.03");
List<String> standardizedDates = dateStrs.stream()
    .map(dateStr -> {
        Date date = DateUtil.parse(dateStr);
        return DateUtil.format(date, "yyyy-MM-dd");
    })
    .collect(Collectors.toList());

// 标准化手机号格式
String phone = "138 1234 5678";
String standardizedPhone = phone.replaceAll("\\s+", ""); // 13812345678

// 标准化邮箱格式
String email = "USER@EXAMPLE.COM";
String standardizedEmail = email.toLowerCase(); // user@example.com

# 4. 数据验证

// 验证邮箱格式
boolean isEmail = Validator.isEmail("user@example.com"); // true

// 验证手机号格式
boolean isPhone = Validator.isMobile("13812345678"); // true

// 验证日期格式
boolean isDate = Validator.isDate("2023-01-01"); // true

// 验证数字范围
boolean isInRange = Validator.isBetween(50, 0, 100); // true

// 自定义验证规则
boolean isValid = Validator.isMatchRegex("^[a-zA-Z0-9]+$", "abc123"); // true

# 5. 数据过滤

// 按条件过滤集合
List<Integer> numbers = CollUtil.newArrayList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = CollUtil.filter(numbers, number -> number % 2 == 0); // [2, 4]

// 移除不符合条件的数据
CollUtil.removeIf(numbers, number -> number < 3); // [3, 4, 5]

// 分页过滤
List<String> largeList = CollUtil.newArrayList();
for (int i = 0; i < 1000; i++) {
    largeList.add("item" + i);
}
List<String> pageList = CollUtil.page(largeList, 1, 20); // 获取第2页,每页20条

# 四、数据入库

数据入库是将清洗后的数据保存到数据库的过程。

# 1. 单条数据入库

// 创建实体对象
Entity user = Entity.create("user")
    .set("name", "张三")
    .set("age", 25)
    .set("email", "zhangsan@example.com")
    .set("create_time", new Date());

// 插入数据
Db.use().insert(user);

// 插入数据并返回自增主键
Long id = Db.use().insertForGeneratedKey(user);

# 2. 批量数据入库

// 创建数据列表
List<Entity> userList = CollUtil.newArrayList();
for (int i = 0; i < 100; i++) {
    Entity user = Entity.create("user")
        .set("name", "用户" + i)
        .set("age", 20 + i % 30)
        .set("email", "user" + i + "@example.com")
        .set("create_time", new Date());
    userList.add(user);
}

// 批量插入数据
Db.use().insert(userList);

# 3. 使用事务入库

// 使用事务确保数据一致性
Db.use().tx(db -> {
    // 插入用户
    Entity user = Entity.create("user")
        .set("name", "张三")
        .set("age", 25);
    Long userId = db.insertForGeneratedKey(user);

    // 插入用户详情
    Entity userDetail = Entity.create("user_detail")
        .set("user_id", userId)
        .set("address", "北京")
        .set("phone", "13812345678");
    db.insert(userDetail);
});

# 4. 数据更新

// 更新数据
Db.use().update(
    Entity.create().set("age", 26), // 更新内容
    Entity.create("user").set("name", "张三") // 更新条件
);

# 💡 完整示例

# 示例1:网页数据清洗与入库

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.http.HttpUtil;

public class WebDataCleaning {

    public static void main(String[] args) {
        try {
            // 1. 数据抽取:获取网页内容
            String url = "https://www.example.com/news";
            String html = HttpUtil.get(url);

            // 2. 数据抽取:提取新闻列表
            List<String> newsItems = ReUtil.findAll("<div class=\"news-item\">(.*?)</div>", html, 0);

            Console.log("找到 {} 条新闻", newsItems.size());

            // 3. 数据转换与清洗
            List<Entity> newsList = CollUtil.newArrayList();

            for (String item : newsItems) {
                try {
                    // 提取新闻标题
                    String title = ReUtil.get("<h3><a href=\"(.*?)\">(.*?)</a></h3>", item, 2);
                    String newsUrl = ReUtil.get("<h3><a href=\"(.*?)\">(.*?)</a></h3>", item, 1);
                    String publishDateStr = ReUtil.get("<span class=\"date\">(.*?)</span>", item, 1);
                    String author = ReUtil.get("<span class=\"author\">(.*?)</span>", item, 1);
                    String content = ReUtil.get("<p class=\"content\">(.*?)</p>", item, 1);

                    // 数据清洗
                    if (StrUtil.isBlank(title)) continue;

                    // 数据转换
                    Date publishDate = DateUtil.parse(publishDateStr);
                    author = StrUtil.emptyToDefault(author, "未知作者");
                    content = StrUtil.emptyToDefault(content, "无内容");

                    // 创建实体对象
                    Entity news = Entity.create("news")
                        .set("title", title)
                        .set("url", newsUrl)
                        .set("publish_date", publishDate)
                        .set("author", author)
                        .set("content", content)
                        .set("create_time", DateUtil.date());

                    newsList.add(news);
                } catch (Exception e) {
                    Console.error("解析新闻失败: {}", e.getMessage());
                }
            }

            // 4. 数据去重
            Set<String> existingUrls = CollUtil.newHashSet();
            List<Entity> uniqueNewsList = CollUtil.newArrayList();

            for (Entity news : newsList) {
                String url = news.getStr("url");
                if (!existingUrls.contains(url)) {
                    existingUrls.add(url);
                    uniqueNewsList.add(news);
                }
            }

            Console.log("去重后剩余 {} 条新闻", uniqueNewsList.size());

            // 5. 数据入库
            if (CollUtil.isNotEmpty(uniqueNewsList)) {
                Db.use().insert(uniqueNewsList);
                Console.log("成功入库 {} 条新闻", uniqueNewsList.size());
            }

        } catch (Exception e) {
            Console.error("数据清洗失败: {}", e.getMessage());
        }
    }
}

# 示例2:CSV数据清洗与入库

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.csv.CsvReader;
import cn.hutool.csv.CsvUtil;
import cn.hutool.io.FileUtil;

public class CsvDataCleaning {

    public static void main(String[] args) {
        try {
            // 1. 数据抽取:读取CSV文件
            CsvReader reader = CsvUtil.getReader();
            List<cn.hutool.csv.CsvRow> rows = reader.read(FileUtil.file("data.csv"));

            Console.log("读取到 {} 行数据", rows.size());

            // 2. 数据转换与清洗
            List<Entity> dataList = CollUtil.newArrayList();

            for (int i = 1; i < rows.size(); i++) { // 跳过表头
                cn.hutool.csv.CsvRow row = rows.get(i);

                try {
                    // 提取字段
                    String idStr = row.get(0);
                    String name = row.get(1);
                    String ageStr = row.get(2);
                    String birthdayStr = row.get(3);
                    String salaryStr = row.get(4);

                    // 数据清洗
                    if (StrUtil.isBlank(idStr) || StrUtil.isBlank(name)) continue;

                    // 数据转换
                    int id = NumberUtil.parseInt(idStr);
                    int age = StrUtil.isNotBlank(ageStr) ? NumberUtil.parseInt(ageStr) : 0;
                    Date birthday = StrUtil.isNotBlank(birthdayStr) ? DateUtil.parse(birthdayStr) : null;
                    double salary = StrUtil.isNotBlank(salaryStr) ? NumberUtil.parseDouble(salaryStr) : 0.0;

                    // 创建实体对象
                    Entity data = Entity.create("employee")
                        .set("id", id)
                        .set("name", name)
                        .set("age", age)
                        .set("birthday", birthday)
                        .set("salary", salary)
                        .set("create_time", DateUtil.date());

                    dataList.add(data);
                } catch (Exception e) {
                    Console.error("解析第 {} 行数据失败: {}", i + 1, e.getMessage());
                }
            }

            // 3. 数据去重
            Set<Integer> existingIds = CollUtil.newHashSet();
            List<Entity> uniqueDataList = CollUtil.newArrayList();

            for (Entity data : dataList) {
                Integer id = data.getInt("id");
                if (!existingIds.contains(id)) {
                    existingIds.add(id);
                    uniqueDataList.add(data);
                }
            }

            Console.log("去重后剩余 {} 条数据", uniqueDataList.size());

            // 4. 数据入库
            if (CollUtil.isNotEmpty(uniqueDataList)) {
                Db.use().insert(uniqueDataList);
                Console.log("成功入库 {} 条数据", uniqueDataList.size());
            }

        } catch (Exception e) {
            Console.error("CSV数据清洗失败: {}", e.getMessage());
        }
    }
}

# 示例3:JSON数据清洗与入库

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

public class JsonDataCleaning {

    public static void main(String[] args) {
        try {
            // 1. 数据抽取:从API获取JSON数据
            String apiUrl = "https://api.example.com/users";
            String jsonStr = HttpUtil.get(apiUrl);

            // 2. 解析JSON数据
            JSONObject json = JSONUtil.parseObj(jsonStr);
            JSONArray usersArray = json.getJSONArray("users");

            Console.log("获取到 {} 个用户数据", usersArray.size());

            // 3. 数据转换与清洗
            List<Entity> userList = CollUtil.newArrayList();

            for (int i = 0; i < usersArray.size(); i++) {
                try {
                    JSONObject userJson = usersArray.getJSONObject(i);

                    // 提取字段
                    String username = userJson.getStr("username");
                    String email = userJson.getStr("email");
                    String phone = userJson.getStr("phone");
                    String createdAt = userJson.getStr("created_at");
                    JSONObject addressJson = userJson.getJSONObject("address");

                    // 数据清洗
                    if (StrUtil.isBlank(username) || StrUtil.isBlank(email)) continue;
                    if (!Validator.isEmail(email)) continue;

                    // 数据转换
                    Date createTime = DateUtil.parse(createdAt);
                    String city = addressJson != null ? addressJson.getStr("city", "") : "";
                    String country = addressJson != null ? addressJson.getStr("country", "") : "";

                    // 标准化手机号
                    String standardizedPhone = StrUtil.isNotBlank(phone)
                        ? phone.replaceAll("[^0-9+"]", "")
                        : "";

                    // 创建实体对象
                    Entity user = Entity.create("user")
                        .set("username", username)
                        .set("email", email)
                        .set("phone", standardizedPhone)
                        .set("city", city)
                        .set("country", country)
                        .set("created_at", createTime)
                        .set("update_time", DateUtil.date());

                    userList.add(user);
                } catch (Exception e) {
                    Console.error("解析第 {} 个用户数据失败: {}", i + 1, e.getMessage());
                }
            }

            // 4. 数据去重
            Set<String> existingEmails = CollUtil.newHashSet();
            List<Entity> uniqueUserList = CollUtil.newArrayList();

            for (Entity user : userList) {
                String email = user.getStr("email");
                if (!existingEmails.contains(email)) {
                    existingEmails.add(email);
                    uniqueUserList.add(user);
                }
            }

            Console.log("去重后剩余 {} 个用户数据", uniqueUserList.size());

            // 5. 数据入库
            if (CollUtil.isNotEmpty(uniqueUserList)) {
                Db.use().insert(uniqueUserList);
                Console.log("成功入库 {} 个用户数据", uniqueUserList.size());
            }

        } catch (Exception e) {
            Console.error("JSON数据清洗失败: {}", e.getMessage());
        }
    }
}

# 🎨 高级技巧

# 1. 使用多线程提高效率

// 使用线程池提高数据处理效率
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<?>> futures = CollUtil.newArrayList();

for (String item : items) {
    futures.add(executor.submit(() -> {
        processItem(item);
    }));
}

// 等待所有任务完成
for (Future<?> future : futures) {
    future.get();
}

executor.shutdown();

# 2. 分批处理大数据量

// 分批处理大数据量
List<Entity> allData = getAllData(); // 获取所有数据
int batchSize = 1000;
int total = allData.size();
int batches = NumberUtil.ceil(total, batchSize);

for (int i = 0; i < batches; i++) {
    int start = i * batchSize;
    int end = Math.min((i + 1) * batchSize, total);
    List<Entity> batchData = allData.subList(start, end);

    Db.use().insert(batchData);
    Console.log("已处理 {} / {} 条数据", end, total);
}

# 3. 使用缓存减少重复请求

// 使用缓存减少重复的API请求
Cache<String, String> cache = CacheUtil.newLRUCache(1000);

String getApiData(String url) {
    return cache.get(url, () -> {
        return HttpUtil.get(url);
    }, Duration.ofHours(1)); // 缓存1小时
}

# 4. 数据质量监控

// 数据质量监控
int total = 0;
int valid = 0;
int invalid = 0;
Map<String, Integer> errorStats = CollUtil.newHashMap();

for (String item : items) {
    total++;
    try {
        processItem(item);
        valid++;
    } catch (Exception e) {
        invalid++;
        String errorType = e.getClass().getSimpleName();
        errorStats.put(errorType, errorStats.getOrDefault(errorType, 0) + 1);
    }
}

Console.log("数据质量报告:");
Console.log("总数据量: {}", total);
Console.log("有效数据: {}", valid);
Console.log("无效数据: {}", invalid);
Console.log("错误统计: {}", errorStats);

# 5. 使用事务保证数据一致性

// 使用事务保证数据一致性
Db.use().tx(db -> {
    try {
        // 清理旧数据
        db.execute("DELETE FROM user WHERE last_active < ?", DateUtil.offsetDay(new Date(), -30));

        // 插入新数据
        db.insert(userList);

        // 更新统计信息
        db.execute("UPDATE stats SET user_count = (SELECT COUNT(*) FROM user)");

    } catch (Exception e) {
        // 事务会自动回滚
        throw new RuntimeException("数据处理失败", e);
    }
});

# ⚠️ 注意事项

# 1. 数据备份

在进行数据清洗和入库操作前,务必对原始数据和目标数据库进行备份,以防止数据丢失。

# 2. 错误处理

数据清洗过程中可能会遇到各种错误,如格式错误、网络错误、数据库错误等,务必做好异常处理。

# 3. 性能优化

  • 对于大数据量,使用分批处理和多线程提高效率
  • 使用连接池减少数据库连接开销
  • 合理设置缓存,减少重复请求
  • 优化SQL语句,避免全表扫描

# 4. 数据隐私保护

在处理敏感数据时,要注意数据隐私保护:

  • 对敏感字段进行加密处理
  • 避免在日志中记录敏感信息
  • 遵守相关数据保护法规

# 5. 测试验证

在正式运行前,务必进行充分的测试:

  • 测试数据抽取的准确性
  • 测试数据转换的正确性
  • 测试数据清洗的有效性
  • 测试数据入库的完整性

# 📊 最佳实践

# 1. 建立数据清洗规则

在开始数据清洗前,建立明确的数据清洗规则:

  • 定义数据格式标准
  • 确定缺失值处理策略
  • 制定数据去重规则
  • 建立数据验证标准

# 2. 采用ETL流程

采用经典的ETL(Extract-Transform-Load)流程:

  • Extract:从数据源抽取原始数据
  • Transform:转换和清洗数据
  • Load:将清洗后的数据加载到目标系统

# 3. 日志记录

详细记录数据清洗过程中的日志:

  • 记录数据抽取的来源和数量
  • 记录数据转换的规则和结果
  • 记录数据清洗的过程和统计信息
  • 记录数据入库的结果和时间

# 4. 监控和反馈

建立数据清洗的监控和反馈机制:

  • 监控数据质量指标
  • 定期生成数据质量报告
  • 及时处理数据质量问题
  • 持续优化数据清洗规则

# 5. 文档化

对数据清洗过程进行文档化:

  • 记录数据源的信息
  • 记录数据清洗的规则和流程
  • 记录数据转换的逻辑
  • 记录数据入库的表结构

# 🎯 总结

通过 Hutool 的各种工具类组合使用,可以高效地完成数据清洗的各个环节:

  • 数据抽取:使用 HttpUtil、ReUtil、CsvUtil 等工具从各种数据源获取数据
  • 数据转换:使用 DateUtil、NumberUtil、StrUtil 等工具转换数据格式
  • 数据清洗:使用 CollUtil、Validator、StrUtil 等工具处理数据质量问题
  • 数据入库:使用 Db 模块将清洗后的数据保存到数据库

Hutool 提供的工具类简洁易用,能够大大提高数据清洗的效率和质量。无论是小规模的数据清洗还是大规模的数据处理,Hutool 都能提供合适的解决方案。

在实际应用中,应根据具体需求选择合适的工具类和方法,并结合最佳实践进行数据清洗,以确保数据的准确性、完整性和一致性。

上次更新: 2026/01/03, 21:59:18
数据抽取

← 数据抽取

Theme by Vdoing | Copyright © 2025-2026 Hutool | Apache-2.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式