0
\$\begingroup\$

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?

\$\endgroup\$
3
\$\begingroup\$

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;
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You could also use Predicate.not( this::isEvenNumber ) if you want to reduce the number of own methods \$\endgroup\$ – RobAu Jun 14 at 11:15
0
\$\begingroup\$

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);
\$\endgroup\$
0
\$\begingroup\$

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;
}
```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.