展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > Java实现列表均匀分块策略:对标Numpy array_split

Java实现列表均匀分块策略:对标Numpy array_split

本文探讨了在Java中如何将一个列表(或数组)均匀地分割成指定数量的子列表,以模拟PythonNumPy库中array_split函数的行为。我们将介绍一种基于Guava库Lists.partition方法的实现策略,通过精确计算每个子列表的最大容量,实现灵活且高效的数据分块处理,适用于并行处理或数据分页等场景。

Java实现列表均匀分块策略:对标Numpy array_split

本文探讨了在Java中如何将一个列表(或数组)均匀地分割成指定数量的子列表,以模拟Python NumPy库中array_split函数的行为。我们将介绍一种基于Guava库Lists.partition方法的实现策略,通过精确计算每个子列表的最大容量,实现灵活且高效的数据分块处理,适用于并行处理或数据分页等场景。

1. 理解需求:Numpy array_split 的行为

在Python的NumPy库中,numpy.array_split(array, n) 函数能够将一个数组分割成 n 个大致相等的子数组。即使数组的长度不能被 n 整除,它也会尽量使子数组的大小均匀分布,例如:

>>> import numpy
>>> x = [7, 3, 9, 10, 5, 6, 8, 13] # 长度为8的列表
>>> numpy.array_split(x, 3) # 分割成3个子数组
[array([7, 3, 9]), array([10,  5,  6]), array([ 8, 13])]

在这个例子中,一个包含8个元素的列表被分成了3个子列表,其长度分别为3、3、2。这种“按数量分块”的需求在Java中进行数据并行处理或分页时非常常见。

2. Java 实现策略:结合 Guava Lists.partition

Java标准库中没有直接对应 numpy.array_split 的函数。然而,通过巧妙地结合 Guava 库的 Lists.partition 方法和数学计算,我们可以实现相同的逻辑。

Lists.partition(list, size) 方法的作用是将一个列表分割成若干个子列表,每个子列表的最大长度为 size。最后一个子列表的长度可能会小于 size。 为了模拟 array_split 的“分割成 n 块”行为,我们需要首先计算出每个子列表的 最大容量 size,使得原始列表能够被分割成恰好 n 块。

2.1 计算子列表的最大容量

假设原始列表的长度为 totalSize,我们希望将其分割成 numberOfChunks 个子列表。 每个子列表的最大容量 sublistMaxSize 可以通过以下公式计算:

sublistMaxSize = Math.ceil(totalSize / (double) numberOfChunks)

这里使用 (double) 进行浮点除法,并使用 Math.ceil 向上取整。这样做的目的是确保:

  • 如果 totalSize 能被 numberOfChunks 整除,sublistMaxSize 就是精确的平均值。
  • 如果不能整除,sublistMaxSize 会向上取整,这意味着每个子列表(除了最后一个可能较小)都将拥有这个最大容量,从而保证最终的子列表数量不会超过 numberOfChunks,并且会是期望的 numberOfChunks。

例如,对于长度为8的列表和3个分块: sublistMaxSize = Math.ceil(8 / 3.0) = Math.ceil(2.66...) = 3 这意味着每个子列表的最大容量为3。

2.2 使用 Lists.partition 进行分割

计算出 sublistMaxSize 后,我们就可以直接使用 Lists.partition 方法:

List> partitionedLists = Lists.partition(originalList, sublistMaxSize);

这将返回一个包含所有子列表的列表。

3. 示例代码

以下是一个完整的Java示例,演示如何使用Guava库实现Numpy array_split 的功能:

首先,确保你的项目中已添加Guava依赖。如果你使用Maven,可以在 pom.xml 中添加:


    com.google.guava
    guava
    32.1.3-jre 

然后,是实现代码:

import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ListSplitterExample {

    /**
     * 将一个列表分割成指定数量的子列表,模拟Numpy的array_split行为。
     *
     * @param originalList 原始列表
     * @param numberOfChunks 期望的子列表数量
     * @param  列表中元素的类型
     * @return 包含所有子列表的列表
     * @throws IllegalArgumentException 如果 numberOfChunks 小于等于 0
     */
    public static  List> splitListIntoChunks(List originalList, int numberOfChunks) {
        if (numberOfChunks <= 0) {
            throw new IllegalArgumentException("子列表数量必须大于0。");
        }
        if (originalList.isEmpty()) {
            return new ArrayList<>(); // 空列表直接返回空结果
        }

        // 计算原始列表的总长度
        int totalSize = originalList.size();

        // 计算每个子列表的最大容量
        // 使用Math.ceil确保向上取整,以保证最终的子列表数量不会超过numberOfChunks
        int sublistMaxSize = (int) Math.ceil(totalSize / (double) numberOfChunks);

        // 使用Guava的Lists.partition方法进行分割
        // Lists.partition会创建固定大小的子列表,最后一个可能较小
        // 由于我们精确计算了sublistMaxSize,最终的子列表数量将是numberOfChunks
        return Lists.partition(originalList, sublistMaxSize);
    }

    public static void main(String[] args) {
        // 示例数据
        List data = Arrays.asList(7, 3, 9, 10, 5, 6, 8, 13);
        int chunks = 3; // 期望分割成3个子列表

        System.out.println("原始列表: " + data);
        System.out.println("期望分块数量: " + chunks);

        // 调用分块方法
        List> partitionedData = splitListIntoChunks(data, chunks);

        System.out.println("分割后的子列表:");
        for (int i = 0; i < partitionedData.size(); i++) {
            System.out.println("  子列表 " + (i + 1) + ": " + partitionedData.get(i));
        }

        // 另一个示例:分割成5个子列表
        List words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry", "fig", "grape");
        int wordChunks = 5;
        System.out.println("\n--- 另一个示例 ---");
        System.out.println("原始列表: " + words);
        System.out.println("期望分块数量: " + wordChunks);
        List> partitionedWords = splitListIntoChunks(words, wordChunks);
        System.out.println("分割后的子列表:");
        for (int i = 0; i < partitionedWords.size(); i++) {
            System.out.println("  子列表 " + (i + 1) + ": " + partitionedWords.get(i));
        }

        // 边缘情况:分块数量大于列表长度
        List smallList = Arrays.asList(1, 2, 3);
        int smallListChunks = 5;
        System.out.println("\n--- 边缘情况:分块数量大于列表长度 ---");
        System.out.println("原始列表: " + smallList);
        System.out.println("期望分块数量: " + smallListChunks);
        List> partitionedSmallList = splitListIntoChunks(smallList, smallListChunks);
        System.out.println("分割后的子列表:");
        for (int i = 0; i < partitionedSmallList.size(); i++) {
            System.out.println("  子列表 " + (i + 1) + ": " + partitionedSmallList.get(i));
        }
    }
}

输出示例:

原始列表: [7, 3, 9, 10, 5, 6, 8, 13]
期望分块数量: 3
分割后的子列表:
  子列表 1: [7, 3, 9]
  子列表 2: [10, 5, 6]
  子列表 3: [8, 13]

--- 另一个示例 ---
原始列表: [apple, banana, cherry, date, elderberry, fig, grape]
期望分块数量: 5
分割后的子列表:
  子列表 1: [apple, banana]
  子列表 2: [cherry, date]
  子列表 3: [elderberry]
  子列表 4: [fig]
  子列表 5: [grape]

--- 边缘情况:分块数量大于列表长度 ---
原始列表: [1, 2, 3]
期望分块数量: 5
分割后的子列表:
  子列表 1: [1]
  子列表 2: [2]
  子列表 3: [3]

可以看到,当期望分块数量为3时,8个元素的列表被分成了 [3, 3, 2] 三个子列表,与Numpy的行为一致。当期望分块数量为5时,7个元素的列表被分成了 [2, 2, 1, 1, 1] 五个子列表,也符合预期。

4. 注意事项与总结

  • Guava依赖:此方法依赖于Google Guava库。如果项目中不允许引入第三方库,则需要手动实现分块逻辑,这会稍微复杂一些,需要循环和 subList() 方法来完成。
  • 性能:Lists.partition 返回的是原列表的视图(view),而不是创建新的子列表拷贝。这意味着它具有较高的性能,并且内存开销较小。对返回的子列表的修改会影响原始列表。如果需要独立的子列表,应该进行深拷贝。
  • 空列表和分块数量:示例代码已处理了空列表和 numberOfChunks <= 0 的情况。当 numberOfChunks 大于原始列表长度时,每个元素将单独成为一个子列表,其余的子列表将是空列表(如果 sublistMaxSize 计算结果为1,且列表元素数量少于 numberOfChunks,则 Lists.partition 会返回与原始列表长度相同的子列表数量,每个子列表包含一个元素,这与Numpy array_split 在这种情况下返回的行为一致)。
  • 通用性:splitListIntoChunks 方法是泛型的,可以处理任何类型的列表。

通过这种结合数学计算和Guava Lists.partition 的策略,我们可以在Java中优雅且高效地实现类似于Numpy array_split 的列表分块功能,这对于处理大规模数据、实现并行计算任务或构建分页逻辑都非常有用。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。