如何高效的匹配、筛选数据,避免嵌套循环

在处理大量数据时,使用嵌套循环来进行数据匹配是非常低效的,尤其是在数据集较大的情况下。利用 Map 结构可以显著提高数据匹配的效率。因为使用循环查找方式的时间复杂度是O(n),而使用map的has匹配方式的时间复杂度接近O(1),这大大提高了数据查找能力,尤其是数据量大的时候效率尤其显著。下面介绍几种方法来避免嵌套循环,提高数据筛选和匹配的性能。

1.数据匹配

假如有两个数组数据a和b,a数组里面的元素有个状态值字段status,而b数组则存储这个状态值字段的完整信息,我们的需求是为a数组的每个元素的状态值字段匹配对应的中文名称来展示(字典翻译)。

无脑实现(嵌套循环匹配)

// 遍历数组 a

for (User user : a) {
    // 获取状态值
    Integer status = user.getStatus();
    // 遍历数组 b
    for (DataStatusEnum statusInfo : b) {
        // 匹配状态值
        if (statusInfo.getValue().equals(status)) {
            // 设置中文名
            user.setStatusName(statusInfo.getLabel());
            break;
        }
    }
}
高效实现(利用map匹配)
// 遍历数组 b 转换为map
Map<Integer, String> map = new HashMap<>(b.length);
for (DataStatusEnum statusInfo : b) {
    map.put(statusInfo.getValue(), statusInfo.getLabel());
}
// 遍历数组 a
for (User user : a) {
    // 映射中文名
    String statusName = map.get(user.getStatus());
    // 设置中文名
    user.setStatusName(statusName);
}
js写法(利用map)
// 遍历数组 b 转换为map
const map = new Map<number, string>();
for (const statusInfo of b) {
    map.set(statusInfo.value, statusInfo.label);
}
// 遍历数组 a
for (const user of a) {
    // 映射中文名
    const statusName = map.get(user.status);
    // 设置中文名
    user.statusName = statusName;
}
js写法(利用对象)
// 遍历数组 b 转换为对象
const map: any = {};
for (const statusInfo of b) {
    map[statusInfo.value] = statusInfo.label;
}
// 遍历数组 a
for (const user of a) {
    // 映射中文名
    const statusName = map[user.status];
    // 设置中文名
    user.statusName = statusName;
}

2.数据筛选

假如有两个数组数据a和b,a数组的元素里面有个id字段,而b数组的元素则有个aid字段存储的是a数组元素的id字段的值,我们的需求是找出在b数组中存有其id的的所有a数组元素。
无脑实现(嵌套循环匹配)

a = a.stream().filter(ax -> {
    // 获取状态值
    Long id = ax.getId();
    // 遍历数组 b
    for (UserNotice bx : b) {
        // 匹配id
        if (Objects.equals(id, bx.getAid())) {
            return true;
        }
    }
    return false;
}).collect(Collectors.toList());
高效实现(利用map匹配)
// 遍历数组 b 转换为set
Set<Long> set = b.stream()
    .map(UserNotice::getAid)
    .collect(Collectors.toSet());
// 筛选数据
a = a.stream()
    .filter(x -> set.contains(x.getId()))
    .collect(Collectors.toList());
js写法(利用set)
// 遍历数组 b 转换为set
const set = new Set<string>();
for (const bx of b) {
    set.add(bx.aid);
}
// 筛选数据
a = a.filter(ax => set.has(ax.id))
js写法(利用对象)
// 遍历数组 b 转换为对象
const map: any = {};
for (const bx of b) {
    map[bx.aid] = true;
}
// 筛选数据
a = a.filter(ax => map[ax.id])

3.总结

从以上可以看出,我们将b数组数据转换为map只需遍历遍历一次b数组,而后匹配过程基于has函数,几乎无循环遍历过程,相比于在a数组遍历里面遍历b数组效率要高得多,因为嵌套方式是a数组有多少元素就要遍历多少次b数组,数据量少时体现不出什么,当数据量很大时就会有极大的性能差异,所以开发过程中如果遇到这种需求可以考虑下本文提供的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值