1
\$\begingroup\$
public static void main(String[] args) {
    int minKmh = 10;
    int maxKmh = 20;
    int step = 5;

    String allSpeeds = "";
    while (minKmh <= maxKmh) {
        allSpeeds += minKmh + ",";
        minKmh += step;
    }
    String[] allSpeedsAsArray = removeLastChar(allSpeeds).split(","); // result: 10,15,20

}

private static String removeLastChar(String str) {
    return str.substring(0, str.length() - 1);
}

I have a minimum car speed and a maximum car speed. In this case 10 and 20. And I want every speed which is between minimum and maximum where the speed gets incremented by a step speed.

I don't like my current version because it is large in my opinion. Is it possible to shorten the code to 1-2 liner?

\$\endgroup\$
1
  • \$\begingroup\$ Use a for loop and remember clarity is not about the fewest number of lines if are long and convoluted. \$\endgroup\$ Jul 19, 2018 at 18:12

2 Answers 2

5
\$\begingroup\$

First off, you should capture this functionality in a dedicated method, rather than in the class' main method.

Secondly, I'm not sure why you want an array of String. I don't know the context, but as you're already calculating with speeds, it seems likely you'll calculate more with them further on, and you'll want them to be numbers again.

Next, your method of doing this is appending everything in one giant String, and then splitting it again, after dealing with an unnecessary separator at the end. Looks like a lot of work for nothing. You can just add everything to an array directly (you'll have to precalculate its size beforehand though)

Java 8 has IntStream, which is ideal for this task. It enables the one-liner you're looking for.

private int[] allSpeeds(int lower, int upper, int step) {
    return IntStream.iterate(lower, i -> i + step)
            .limit(Math.max(0, ((upper - lower) / step) + 1)) // limit to the needed size, ensure this value cannot be negative
            .toArray();
}
\$\endgroup\$
2
  • \$\begingroup\$ Limit can't just be upper? \$\endgroup\$
    – Teddy
    Jul 22, 2018 at 9:04
  • 1
    \$\begingroup\$ @Teddy No, since limit takes a number of elements in the stream \$\endgroup\$
    – bowmore
    Jul 22, 2018 at 14:27
2
\$\begingroup\$

As of Java-9, there exists IntStream.html#iterate(seed, hasNext, next)

If you are trying to get a comma separated list of speeds, use:

String allSpeeds = IntStream.iterate(minKmh, i -> i <= maxKmh, i -> i + step)
                            .mapToObj(Integer::toString)
                            .collect( Collectors.joining( "," ) );

Or, if you want the array of speeds as Strings:

String[] allSpeedsAsArray = IntStream.iterate(minKmh, i -> i <= maxKmh, i -> i + step)
                                     .mapToObj(Integer::toString)
                                     .toArray();

Finally, improving @bowman's solution, slightly:

int[] speeds = IntStream.iterate(minKmh, i -> i <= maxKmh, i -> i + step).toArray();

Although, the above solutions require step > 0 or they may not terminate, where as Bowman's solution works fine with negative step sizes.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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