1. 概述

在Java中处理整数时,我们有时需要将它们分解成单个数字,以完成各种计算或数据操作任务。

在这篇教程中,我们将探讨使用Java分解一个整数为各个组成数字的不同方法。

2. 问题介绍

让我们通过一个例子来理解这个问题。假设我们有一个整数:

int THE_NUMBER = 1230456;

我们的目标是按照顺序将这个数分解成数字:

1, 2, 3, 0, 4, 5, 6

为了简化,本教程主要关注的是正十进制整数。然而,根据特定需求,我们可能希望得到每个数字作为IntegercharString类型。

接下来,我们将探索不同的方法来适应这些不同的返回类型。

3. 分解为Integer列表

首先,我们将给定的整数分解为一个Integer列表。也就是说,我们目标是获取这样的列表:

List<Integer> EXPECTED_INT_LIST = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6);

一个最直接的方法是使用循环,反复将数字除以10,在每次迭代中提取余数,直到数字变为零

      1230456 / 10 = 123045 Reminder: 6
  |-> 123045 / 10 = 12304 Reminder: 5
  |-> 12304 / 10 = 1230 Reminder: 4
  |-> 1230 / 10 = 123 Reminder: 0
  |-> 123 / 10 = 12 Reminder: 3
  |-> 12 / 10 = 1 Reminder: 2
  |-> 1 / 10 = 0 Reminder: 1

然而,如上所示,这种方法会产生反向的数字顺序。为了解决这个问题,我们可以使用LinkedList作为在每次步骤中将余数推入栈中

int number = THE_NUMBER;
LinkedList<Integer> result = new LinkedList<>();
while (number > 0) {
    result.push(number % 10);
    number /= 10;
}
assertEquals(EXPECTED_INT_LIST, result);

此外,我们也可以使用递归实现相同的想法

void collectDigits(int num, List<Integer> digitList) {
    if (num / 10 > 0) {
        collectDigits(num / 10, digitList);
    }
    digitList.add(num % 10);
}

然后,我们可以调用collectDigits()方法获取结果:

List<Integer> result = new ArrayList<>();
collectDigits(THE_NUMBER, result);
assertEquals(EXPECTED_INT_LIST, result);

如果我们的Java版本是Java 9或更高版本,我们可以使用String.chars()IntStream来获取数字列表:

String numStr = String.valueOf(THE_NUMBER);
List<Integer> result = numStr.chars().map(Character::getNumericValue).boxed().collect(Collectors.toList());
assertEquals(EXPECTED_INT_LIST, result);

如代码所示,我们首先将整数转换为字符串。然后,numStr.chars()方法将数字字符串分解为IntStream中的字符。接下来,Character类的**getNumericValue()**方法从IntStream中的字符获取数字作为int。最后,我们将int值装箱成Integer,并使用收集器收集结果到一个列表中。

4. 分解为char数组

有时,我们希望将给定的整数分解为char[]数组:

char[] EXPECTED_CHAR_ARRAY = new char[] { '1', '2', '3', '0', '4', '5', '6' };

这个任务很简单,因为标准String类提供了toCharArray()方法来将字符串分解为char[]。我们需要做的只是将整数转换为String并调用toCharArray()方法:

String numStr = String.valueOf(THE_NUMBER);
char[] result = numStr.toCharArray();
assertArrayEquals(EXPECTED_CHAR_ARRAY, result);

当然,如果需要,我们可以快速地将数组转换为列表。

5. 分解为String数组或String列表

最后,让我们看看如何将一个整数分解为String[]数组或String列表:

String[] EXPECTED_STR_ARRAY = new String[] { "1", "2", "3", "0", "4", "5", "6" };
List<String> EXPECTED_STR_LIST = Lists.newArrayList("1", "2", "3", "0", "4", "5", "6");

既然我们称这个操作为“分割”,那么强大的split()方法可以帮助我们解决问题:

String numStr = String.valueOf(THE_NUMBER);
String[] result = numStr.split("(?<=.)");
assertArrayEquals(EXPECTED_STR_ARRAY, result);

如我们所见,代码看起来相当简洁。关键是我们split()函数中使用的正则表达式模式。**(?<=.)是一个向前查找表达式**。例如,"(?<=X)a"匹配所有紧跟在X字符之后的'a'

然而,我们的模式中只有(?<=.)。这意味着这个模式匹配零宽度的“字符”。所以,split()方法会把任何字符后的零宽度“字符”作为分隔符。如果将数字字符串中的零宽度“字符”替换为'#',可能会更容易理解:“1#2#3#0#4#5#6#”。

另外,split()方法默认会丢弃尾随的空元素。因此,它能产生我们想要的结果。

6. 总结

在这篇文章中,我们探讨了多种将整数分解为数字的方法,并通过示例展示了如何根据不同的类型(如IntegercharString)获取这些数字。

一如既往,每个示例的完整源代码可在GitHub上找到。