# Luhn algorithm using Stream API

Example

String creditCardNumber1 = "4561261212345467";
int sum = IntStream.range(0, creditCardNumber1.length()).filter(i -> i % 2 != 0).map(i -> Character.getNumericValue(creditCardNumber1.charAt(i))).sum() + IntStream.range(0, creditCardNumber1.length()).filter(i -> i % 2 == 0).map(i -> Character.getNumericValue(creditCardNumber1.charAt(i)))
.map(value -> {
int newValue;
if ((newValue = value * 2) > 9) {
newValue = newValue - 9;
}
return newValue;
}).sum();
System.out.println(sum % 10 == 0);


I want to do it by using only one Stream because my code Is unreadable and not effective, is It possible?

I cannot help but ask myself if they don't teach you methods anymore today.

Use methods whith meaningful names, use variables with meaningful names, when you do streams use line breaks with one operation per line. Refrain from supposedly "clever tricks" like doing an actual calculation in an if.

Rewrite of your code (whithout testing or understanding, just formally):

String creditCardNumber1 = "4561261212345467";
int sumOfOddNumbers = IntStream.range(0, creditCardNumber1.length())
.filter(this::isOddNumber)
.map(creditCardNumber1::charAt)
.mapToInt(Character::getNumericValue)
.sum()

int sumOfWhateverThisIs = IntStream.range(0, creditCardNumber1.length())
.filter(this::isEvenNumber)
.map(creditCardNumber1::charAt)
.mapToInt(Character::getNumericValue)
.map(this::giveThisMethodAGoodNameWhichExplainsWhatItDoes)
.sum();

int sum = sumOfOddNumbers + sumOfWhateverThisIs;

System.out.println(sum % 10 == 0);

private boolean isOddNumber(int number) {
return i % 2 != 0;
}

private boolean isEvenNumber(int number) {
return i % 2 == 0;
}

private int giveThisMethodAGoodNameWhichExplainsWhatItDoes(int number) {
int newValue = number * 2;
if (newValue > 9) {
newValue = newValue - 9;
}
return newValue;
}

• You could also use Predicate.not( this::isEvenNumber ) if you want to reduce the number of own methods – RobAu Jun 14 at 11:15

To only have one stream, push down the decision of separating odd and even values:

int sum = IntStream.range(0, creditCardNumber1.length())
.map(i -> {
int value = Character.getNumericValue(creditCardNumber1.charAt(i));
if (i % 2 == 0) {
value = value * 2;
}
return value;
})
.map(value -> value > 9 ? value - 9 : value)
.sum();
System.out.println(sum % 10 == 0);


It can be done with one stream like this:

public static int calculateLuhnChecksum(String creditCardNumber) {
int luhnSum = IntStream.range(0, creditCardNumber.length())
.mapToInt(i -> {
char c = creditCardNumber.charAt(i);
int value = Character.getNumericValue(c);

if(isEven(i)) { // i % 2 != 0 - remember, index starts with 0, so you have "even" numbers at odd indices
value *= 2;
}

return sumOfDigits(value);
})
.sum();

return (luhnSum * 9) % 10;
}

private static int sumOfDigits(int value) {
if(value > 9) {
return value - 9;
}

return value;
}
$$$$
`