用java8流计算Luhn算法

用java8流计算Luhn算法,java,algorithm,java-8,java-stream,Java,Algorithm,Java 8,Java Stream,我正试图借助Java8中的流API验证一个数字 private void ValidateIMEI() { field //a field holding an IMEI Number .getText().chars() .map(this::ConvertASCIIToNumer); } 我被卡住的部分是将偶数加倍,然后除以10 最初,我尝试了传统的for循环: private void ValidateIMEI() { in

我正试图借助Java8中的流API验证一个数字

private void ValidateIMEI() {
    field //a field holding an IMEI Number
            .getText().chars()
            .map(this::ConvertASCIIToNumer);
}
我被卡住的部分是将偶数加倍,然后除以10

最初,我尝试了传统的for循环:

private void ValidateIMEI() {
    int[] numbers = field //a field holding an IMEI Number
            .getText().chars()
            .map(this::ConvertASCIIToNumer).toArray();

    int sum = 0;
    for (int i = 0; i < numbers.length; i++) {
        //Double the even number and divide it by 10. add quotient and remainder
        if ((numbers[i]+1) % 2 == 0) {
            numbers[i] = numbers[i] * 2;
            numbers[i] = numbers[i] / 10 + numbers[i] % 10;
        }
        sum += numbers[i];
    }

    if (sum%10==0) {
        status.setText("Valid");
    }
    else{
        status.setText("InValid");
    }        
}

您的错误是,当您应该将索引为偶数的数字加倍时,您将偶数加倍。由于索引在这个算法中很重要,我建议使用
IntStream
索引:

boolean isValid =
    IntStream.range(0,numbers.length)
             .map (i -> (((i%2) ^ (numbers.length%2)) == 0) ? ((2*numbers[i])/10+(2*numbers[i])%10) : numbers[i])
             .sum() % 10 == 0;
编辑:我刚刚更改了条件,因为数组的长度决定了奇数索引还是偶数索引应该乘以2

如果数组的长度为偶数,则偶数索引中的数字应加倍:

Index 0 1 2 3 4 5

Digit 1 5 2 5 2 6
      -   -   -
如果数组长度为奇数,则奇数索引中的数字应为两位数:

Index 0 1 2 3 4

Digit 1 5 2 5 2
        -   -

这是我能做的最漂亮的:

String num; // your IMEI number
int[] a = {num.length() % 2 == 0 ? 1 : 2};        // 1 if length even, 2 otherwise
boolean isLuhn = num.chars()
        .map(i -> i - '0')         // convert to the int equivalent
        .map(n -> n * (a[0] = a[0] == 1 ? 2 : 1)) // multiply by 1, 2 alternating
        .map(n -> n > 9 ? n - 9 : n)              // handle sum of digits
        .sum() % 10 == 0;                         // mod 10 should be zero

这里使用的“技巧”是使用
int[]
,而不是
int
,变量来保存乘数。这是一种仅允许引用“有效最终”变量的变通方法;数组引用实际上是最终的,但是它的内容(只有一个元素)不是必须的

woha int无法转换为布尔值。我将把a^b==0替换为a==b。或者,您只能迭代到
数字
数组长度的一半,并在每次迭代中处理一对数字。@RiaD或
(i-numbers.length())%2==0
。(我知道,对于负数
I
s和非常长的数组,这会溢出,但我们碰巧知道,在我们的例子中,这两种情况都不正确。)当您实际需要
char
s时,不需要拆分为字符串。换句话说,不要使用
Arrays.stream(num.split(“”)
。您只需要
num.chars().map(c->c-'0')
…@Holger omg。。。一直以来,我都没有注意到这种方法。感谢您的课程:)第一个
.map()
中的
i
与上面定义的变量
int[]i
冲突。我收到以下错误:
Lambda表达式的参数我无法重新声明在封闭范围中定义的另一个局部变量。
@maxyme-Ah。我现在修好了。(我通常手边没有编译器,因为我的大部分代码都是通过手机输入的)
String num; // your IMEI number
int[] a = {num.length() % 2 == 0 ? 1 : 2};        // 1 if length even, 2 otherwise
boolean isLuhn = num.chars()
        .map(i -> i - '0')         // convert to the int equivalent
        .map(n -> n * (a[0] = a[0] == 1 ? 2 : 1)) // multiply by 1, 2 alternating
        .map(n -> n > 9 ? n - 9 : n)              // handle sum of digits
        .sum() % 10 == 0;                         // mod 10 should be zero